Compare commits
2 Commits
Author | SHA1 | Date |
---|---|---|
Sarah Jamie Lewis | f8a9b2c67f | |
Sarah Jamie Lewis | 15e4793ba8 |
57
.drone.yml
57
.drone.yml
|
@ -8,7 +8,7 @@ clone:
|
|||
|
||||
steps:
|
||||
- name: clone
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.19.3
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.13.4
|
||||
environment:
|
||||
buildbot_key_b64:
|
||||
from_secret: buildbot_key_b64
|
||||
|
@ -24,7 +24,7 @@ steps:
|
|||
- git checkout $DRONE_COMMIT
|
||||
|
||||
- name: fetch
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.19.3
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.13.4
|
||||
volumes:
|
||||
- name: deps
|
||||
path: /root/.pub-cache
|
||||
|
@ -47,7 +47,7 @@ steps:
|
|||
# #Todo: fix all the lint errors and add `-set_exit_status` above to enforce linting
|
||||
|
||||
- name: build-linux
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.19.3
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.13.4
|
||||
volumes:
|
||||
- name: deps
|
||||
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`
|
||||
- linux/package-release.sh
|
||||
- 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
|
||||
- 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 --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
|
||||
- cd deb
|
||||
- dpkg-deb --build cwtch
|
||||
- cd ..
|
||||
- mv deb/cwtch.deb cwtch-$VERSION.deb
|
||||
- rm -r deb
|
||||
|
||||
|
||||
- name: linux-ui-tests
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.19.3
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.13.4
|
||||
volumes:
|
||||
- name: deps
|
||||
path: /root/.pub-cache
|
||||
|
@ -86,7 +71,7 @@ steps:
|
|||
- ./run-tests-headless.sh "01_general|01_tor|02_global_settings|04_profile_mgmt"
|
||||
|
||||
- name: test-build-android
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.19.3
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.13.4
|
||||
when:
|
||||
event: pull_request
|
||||
volumes:
|
||||
|
@ -96,7 +81,7 @@ steps:
|
|||
- flutter build apk --debug
|
||||
|
||||
- name: build-android
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.19.3
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.13.4
|
||||
when:
|
||||
event: push
|
||||
environment:
|
||||
|
@ -120,7 +105,7 @@ steps:
|
|||
#- cp build/app/outputs/flutter-apk/app-debug.apk deploy/android
|
||||
|
||||
- name: widget-tests
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.19.3
|
||||
image: openpriv/flutter-desktop:linux-fstable-3.13.4
|
||||
volumes:
|
||||
- name: deps
|
||||
path: /root/.pub-cache
|
||||
|
@ -129,21 +114,6 @@ steps:
|
|||
- flutter test --coverage
|
||||
- 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
|
||||
image: kroniak/ssh-client
|
||||
pull: if-not-exists
|
||||
|
@ -208,7 +178,7 @@ clone:
|
|||
|
||||
steps:
|
||||
- name: clone
|
||||
image: openpriv/flutter-desktop:windows-sdk30-fstable-3.19.3
|
||||
image: openpriv/flutter-desktop:windows-sdk30-fstable-3.13.4
|
||||
environment:
|
||||
buildbot_key_b64:
|
||||
from_secret: buildbot_key_b64
|
||||
|
@ -226,7 +196,7 @@ steps:
|
|||
- git checkout $Env:DRONE_COMMIT
|
||||
|
||||
- name: fetch
|
||||
image: openpriv/flutter-desktop:windows-sdk30-fstable-3.19.3
|
||||
image: openpriv/flutter-desktop:windows-sdk30-fstable-3.10.2
|
||||
commands:
|
||||
- git describe --tags --abbrev=1 > VERSION
|
||||
- git log -1 --format=%cd --date=format:'%Y-%m-%d-%H-%M' > COMMIT_DATE
|
||||
|
@ -234,12 +204,12 @@ steps:
|
|||
- .\fetch-libcwtch-go.ps1
|
||||
|
||||
- name: build-windows
|
||||
image: openpriv/flutter-desktop:windows-sdk30-fstable-3.19.3
|
||||
image: openpriv/flutter-desktop:windows-sdk30-fstable-3.13.4
|
||||
commands:
|
||||
- flutter pub get
|
||||
- $Env:version += type .\VERSION
|
||||
- $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
|
||||
- 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
|
||||
|
@ -266,7 +236,7 @@ steps:
|
|||
commands:
|
||||
- $Env:version += type .\VERSION
|
||||
- $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:zipsha = $Env:zip + '.sha512.txt'
|
||||
- $Env:buildname = 'flwtch-' + $Env:commitdate + '-' + $Env:version
|
||||
|
@ -291,7 +261,7 @@ steps:
|
|||
- move *.sha512.txt deploy\$Env:builddir
|
||||
|
||||
- name: deploy-windows
|
||||
image: openpriv/flutter-desktop:windows-sdk30-fstable-3.19.3
|
||||
image: openpriv/flutter-desktop:windows-sdk30-fstable-3.13.4
|
||||
when:
|
||||
event: push
|
||||
status: [ success ]
|
||||
|
@ -363,7 +333,6 @@ steps:
|
|||
commands:
|
||||
- export PATH=$PATH:/Users/drone/bin/flutter/bin
|
||||
- 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`
|
||||
- export PATH=$PATH:/opt/homebrew/bin/ #create-dmg
|
||||
- macos/package-release.sh
|
||||
|
|
|
@ -35,7 +35,6 @@ test_home
|
|||
.pub-cache/
|
||||
.pub/
|
||||
/build/
|
||||
./lib/gen/
|
||||
|
||||
# Web related
|
||||
lib/generated_plugin_registrant.dart
|
||||
|
@ -59,7 +58,7 @@ package.
|
|||
# Compiled Libs
|
||||
linux/tor
|
||||
linux/libCwtch.so
|
||||
android/app/cwtch/cwtch.aar
|
||||
android/cwtch/cwtch.aar
|
||||
android/app/src/main/jniLibs/*/libtor.so
|
||||
*.dylib
|
||||
integration_test/gherkin_suite_test.g.dart
|
||||
|
|
|
@ -1 +1 @@
|
|||
2024-02-26-18-01-v0.0.14
|
||||
2024-02-09-13-23-v0.0.11
|
2
LICENSE
2
LICENSE
|
@ -1,5 +1,5 @@
|
|||
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:
|
||||
|
||||
|
|
|
@ -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
|
||||
`
|
|
@ -1,9 +1,3 @@
|
|||
plugins {
|
||||
id "com.android.application"
|
||||
id "kotlin-android"
|
||||
id "dev.flutter.flutter-gradle-plugin"
|
||||
}
|
||||
|
||||
def localProperties = new Properties()
|
||||
def localPropertiesFile = rootProject.file('local.properties')
|
||||
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')
|
||||
if (flutterVersionCode == null) {
|
||||
flutterVersionCode = '1'
|
||||
|
@ -22,6 +21,10 @@ if (flutterVersionName == null) {
|
|||
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)
|
||||
def keystoreProperties = new Properties()
|
||||
def keystorePropertiesFile = rootProject.file('key.properties')
|
||||
|
@ -30,7 +33,7 @@ if (keystorePropertiesFile.exists()) {
|
|||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 34
|
||||
compileSdkVersion 33
|
||||
|
||||
sourceSets {
|
||||
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).
|
||||
applicationId "im.cwtch.flwtch"
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 34
|
||||
targetSdkVersion 33
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
versionName flutterVersionName
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
@ -90,11 +93,11 @@ flutter {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.21" // same as kotlin version in settings.gradle
|
||||
implementation fileTree( dir: 'cwtch')
|
||||
implementation files ('cwtch/cwtch.aar')
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
implementation project(':cwtch')
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.2"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2"
|
||||
implementation "com.airbnb.android:lottie:5.2.0"
|
||||
implementation "androidx.localbroadcastmanager:localbroadcastmanager:1.0.0"
|
||||
implementation "com.android.support.constraint:constraint-layout:2.0.4"
|
||||
|
||||
|
|
|
@ -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">
|
||||
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
|
||||
calls FlutterMain.startInitialization(this); in its onCreate method.
|
||||
|
@ -13,7 +13,7 @@
|
|||
<activity
|
||||
android:name=".MainActivity"
|
||||
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:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize"
|
||||
|
@ -38,30 +38,22 @@
|
|||
android:name="flutterEmbedding"
|
||||
android:value="2" />
|
||||
|
||||
<!--Needed to run in background (lol)-->
|
||||
<service
|
||||
android:name="androidx.work.impl.foreground.SystemForegroundService"
|
||||
android:foregroundServiceType="dataSync"
|
||||
tools:node="merge" />
|
||||
|
||||
</application>
|
||||
|
||||
<!--Needed to access Tor socket-->
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<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" />
|
||||
<!-- 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.
|
||||
Allows app to use ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS -->
|
||||
<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" />
|
||||
|
||||
-->
|
||||
|
||||
<!--Needed to check if activity is foregrounded or if messages from the service should be queued-->
|
||||
<uses-permission android:name="android.permission.GET_TASKS" />
|
||||
|
|
|
@ -11,7 +11,6 @@ import android.graphics.Color
|
|||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import android.content.pm.ServiceInfo
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||
|
@ -23,13 +22,6 @@ import io.flutter.FlutterInjector
|
|||
import org.json.JSONObject
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
import java.io.FileInputStream
|
||||
|
||||
|
||||
import java.io.File
|
||||
|
||||
|
||||
|
||||
|
||||
class FlwtchWorker(context: Context, parameters: WorkerParameters) :
|
||||
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, data.toString());
|
||||
val key = loader.getLookupKeyForAsset(data.getString("picture"))//"assets/profiles/001-centaur.png")
|
||||
var fh : java.io.InputStream? = null;
|
||||
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 fh = applicationContext.assets.open(key)
|
||||
|
||||
val clickIntent = Intent(applicationContext, MainActivity::class.java).also { intent ->
|
||||
intent.action = Intent.ACTION_RUN
|
||||
|
@ -165,21 +145,18 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) :
|
|||
intent.putExtra("ProfileOnion", data.getString("ProfileOnion"))
|
||||
intent.putExtra("Handle", handle)
|
||||
}
|
||||
val image : android.graphics.Bitmap? = if (fh != null) BitmapFactory.decodeStream(fh ) else null;
|
||||
|
||||
val newNotification = NotificationCompat.Builder(applicationContext, channelId)
|
||||
.setContentTitle(data.getString("Nick"))
|
||||
.setContentText((notificationConversationInfo
|
||||
?: "New Message From %1").replace("%1", data.getString("Nick")))
|
||||
.setLargeIcon(image)
|
||||
.setLargeIcon(BitmapFactory.decodeStream(fh))
|
||||
.setSmallIcon(R.mipmap.knott_transparent)
|
||||
.setContentIntent(PendingIntent.getActivity(applicationContext, 1, clickIntent, flags))
|
||||
.setAutoCancel(true)
|
||||
.build()
|
||||
|
||||
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))
|
||||
.build()
|
||||
|
||||
return ForegroundInfo(101, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC)
|
||||
return ForegroundInfo(101, notification)
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package im.cwtch.flwtch
|
||||
|
||||
import SplashView
|
||||
import android.annotation.TargetApi
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
|
@ -18,6 +19,7 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
|||
import androidx.work.*
|
||||
import cwtch.Cwtch
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
import io.flutter.embedding.android.SplashScreen
|
||||
import io.flutter.embedding.engine.FlutterEngine
|
||||
import io.flutter.plugin.common.ErrorLogResult
|
||||
import io.flutter.plugin.common.MethodCall
|
||||
|
@ -30,6 +32,8 @@ import java.util.concurrent.TimeUnit
|
|||
import kotlinx.coroutines.*
|
||||
|
||||
class MainActivity: FlutterActivity() {
|
||||
override fun provideSplashScreen(): SplashScreen? = SplashView()
|
||||
|
||||
|
||||
// Channel to get app info
|
||||
private val CHANNEL_APP_INFO = "test.flutter.dev/applicationInfo"
|
||||
|
@ -573,6 +577,9 @@ class MainActivity: FlutterActivity() {
|
|||
result.success(Cwtch.searchConversations(profile, pattern))
|
||||
return
|
||||
}
|
||||
"ReconnectCwtchForeground" -> {
|
||||
Cwtch.reconnectCwtchForeground()
|
||||
}
|
||||
"Shutdown" -> {
|
||||
Cwtch.shutdownCwtch();
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
|
@ -1,12 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Modify this file to customize your launch splash screen -->
|
||||
<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 -->
|
||||
<item>
|
||||
<!-- <item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@mipmap/knott" />
|
||||
</item>
|
||||
android:src="@mipmap/launch_image" />
|
||||
</item> -->
|
||||
</layer-list>
|
||||
|
|
|
@ -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>
|
|
@ -1,10 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Modify this file to customize your launch splash screen -->
|
||||
<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 -->
|
||||
<item android:drawable="@drawable/knott"
|
||||
android:gravity="center"
|
||||
/>
|
||||
<!-- <item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@mipmap/launch_image" />
|
||||
</item> -->
|
||||
</layer-list>
|
||||
|
|
|
@ -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>
|
|
@ -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
|
@ -1,23 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<!-- 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.Black.NoTitleBar">
|
||||
<!-- 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>
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||
running.
|
||||
|
||||
|
||||
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>
|
||||
</style>
|
||||
</resources>
|
||||
</resources>
|
|
@ -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>
|
|
@ -1,5 +0,0 @@
|
|||
<resources>
|
||||
<color name="darkGreyPurple">#281831</color>
|
||||
<color name="testGreen">#00ff00</color>
|
||||
<color name="ic_launcher_background">@color/darkGreyPurple</color>
|
||||
</resources>
|
|
@ -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 {
|
||||
repositories {
|
||||
google()
|
||||
|
@ -13,6 +28,7 @@ subprojects {
|
|||
project.evaluationDependsOn(':app')
|
||||
}
|
||||
|
||||
tasks.register("clean", Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
||||
//removed due to gradle namespace conflicts that are beyond erinn's mere mortal understanding
|
||||
//task clean(type: Delete) {
|
||||
// delete rootProject.buildDir
|
||||
//}
|
||||
|
|
|
@ -1,25 +1,11 @@
|
|||
pluginManagement {
|
||||
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
|
||||
}()
|
||||
include ':app', ':cwtch'
|
||||
|
||||
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
|
||||
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
|
||||
def properties = new Properties()
|
||||
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
assert localPropertiesFile.exists()
|
||||
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
|
||||
|
||||
plugins {
|
||||
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
||||
id "com.android.application" version "7.4.2" apply false
|
||||
id "org.jetbrains.kotlin.android" version "1.8.21" apply false
|
||||
}
|
||||
|
||||
include ":app"
|
||||
def flutterSdkPath = properties.getProperty("flutter.sdk")
|
||||
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
|
||||
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
|
||||
|
|
Binary file not shown.
|
@ -3,6 +3,6 @@
|
|||
VERSION=`cat LIBCWTCH-GO.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
|
||||
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
|
|
@ -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/tor_icon.dart';
|
||||
import 'package:cwtch/views/profilemgrview.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:flutter/material.dart';
|
||||
|
||||
import 'overrides.dart';
|
||||
|
||||
StepDefinitionGeneric ExpectReply() {
|
||||
return given3<String, String, int, FlutterWorld>(
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_driver/flutter_driver.dart';
|
||||
import 'package:flutter_gherkin/flutter_gherkin.dart';
|
||||
import 'package:gherkin/gherkin.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
||||
enum SwitchState { checked, unchecked }
|
||||
|
||||
|
@ -14,7 +17,6 @@ class SwitchStateParameter extends CustomParameter<SwitchState> {
|
|||
case "unchecked":
|
||||
return SwitchState.unchecked;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:cwtch/themes/opaque.dart';
|
||||
import 'package:cwtch/third_party/linkify/linkify.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
@ -37,7 +38,7 @@ void modalOpenLink(BuildContext ctx, LinkableElement link) {
|
|||
final snackBar = SnackBar(
|
||||
content: Text(
|
||||
AppLocalizations.of(bcontext)!.copiedToClipboardNotification,
|
||||
style: Provider.of<Settings>(bcontext, listen: false).scaleFonts(defaultTextButtonStyle),
|
||||
style: Provider.of<Settings>(bcontext).scaleFonts(defaultTextButtonStyle),
|
||||
),
|
||||
);
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@ abstract class Cwtch {
|
|||
|
||||
// ignore: non_constant_identifier_names
|
||||
Future<void> Start();
|
||||
// ignore: non_constant_identifier_names
|
||||
Future<void> ReconnectCwtchForeground();
|
||||
|
||||
Future<String> getCwtchDir();
|
||||
|
||||
|
|
|
@ -3,10 +3,17 @@ import 'package:cwtch/cwtch/cwtch.dart';
|
|||
import 'package:cwtch/main.dart';
|
||||
import 'package:cwtch/models/appstate.dart';
|
||||
import 'package:cwtch/models/contact.dart';
|
||||
import 'package:cwtch/models/message.dart';
|
||||
import 'package:cwtch/models/messages/VidMessage.dart';
|
||||
import 'package:cwtch/models/profilelist.dart';
|
||||
import 'package:cwtch/models/profileservers.dart';
|
||||
import 'package:cwtch/models/remoteserver.dart';
|
||||
import 'package:cwtch/models/servers.dart';
|
||||
import 'package:cwtch/notification_manager.dart';
|
||||
import 'package:cwtch/views/vidchatview.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:cwtch/torstatus.dart';
|
||||
|
||||
|
@ -58,14 +65,7 @@ class CwtchNotifier {
|
|||
// EnvironmentConfig.debugLog("NewEvent $type $data");
|
||||
switch (type) {
|
||||
case "CwtchStarted":
|
||||
if (data["Reload"] == "true" && profileCN.num > 0) {
|
||||
// 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);
|
||||
}
|
||||
|
||||
flwtchState.cwtch.LoadProfiles(DefaultPassword);
|
||||
appState.SetCwtchInit();
|
||||
break;
|
||||
case "CwtchStartError":
|
||||
|
@ -189,15 +189,45 @@ class CwtchNotifier {
|
|||
break;
|
||||
case "NewMessageFromPeer":
|
||||
var identifier = int.parse(data["ConversationID"]);
|
||||
dynamic message = jsonDecode(data["Data"]);
|
||||
var overlay = int.parse(message['o'].toString());
|
||||
|
||||
if (overlay == VideoOverlay) {
|
||||
try {
|
||||
VidMessage vmsg = VidMessage.fromJson(message);
|
||||
EnvironmentConfig.debugLog("send latency = ${DateTime.now().toUtc().difference(vmsg.s ?? DateTime.now()).inMilliseconds}");
|
||||
EnvironmentConfig.debugLog("tor latency = ${DateTime.now().toUtc().difference(vmsg.t ?? DateTime.now()).inMilliseconds}");
|
||||
EnvironmentConfig.debugLog("recv latency = ${DateTime.now().toUtc().difference(vmsg.r ?? DateTime.now()).inMilliseconds}");
|
||||
|
||||
profileCN.getProfile(data["ProfileOnion"])!.contactList.getContact(identifier)!.vid = vmsg.d;
|
||||
} catch (e) {
|
||||
EnvironmentConfig.debugLog("error decoding video stream: $e: ${message['d']}");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
var messageID = int.parse(data["Index"]);
|
||||
var timestamp = DateTime.tryParse(data['TimestampReceived'])!;
|
||||
var senderHandle = data['RemotePeer'];
|
||||
var senderImage = data['picture'];
|
||||
var isAuto = data['Auto'] == "true";
|
||||
String contenthash = data['ContentHash'];
|
||||
|
||||
var selectedProfile = appState.selectedProfile == data["ProfileOnion"];
|
||||
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(
|
||||
identifier,
|
||||
messageID,
|
||||
|
@ -210,19 +240,6 @@ class CwtchNotifier {
|
|||
selectedProfile,
|
||||
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();
|
||||
break;
|
||||
case "PeerAcknowledgement":
|
||||
|
@ -257,7 +274,7 @@ class CwtchNotifier {
|
|||
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...
|
||||
if (idx >= currentTotal) {
|
||||
if (currentTotal != null && idx >= currentTotal) {
|
||||
// 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
|
||||
// Received refers to the time we actually saw the message from the server
|
||||
|
@ -305,7 +322,6 @@ class CwtchNotifier {
|
|||
break;
|
||||
case "UpdateGlobalSettings":
|
||||
settings.handleUpdate(jsonDecode(data["Data"]));
|
||||
appState.settingsLoaded = true;
|
||||
break;
|
||||
case "UpdatedProfileAttribute":
|
||||
if (data["Key"] == "public.profile.name") {
|
||||
|
@ -350,7 +366,7 @@ class CwtchNotifier {
|
|||
associatedGroups.forEach((identifier) {
|
||||
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) {
|
||||
// No tokens in data...
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import 'dart:convert';
|
|||
import 'dart:ffi';
|
||||
import 'dart:io';
|
||||
import 'dart:isolate';
|
||||
import 'dart:io' show Platform;
|
||||
import 'package:cwtch/cwtch/cwtchNotifier.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
|
@ -12,6 +13,7 @@ import 'package:cwtch/cwtch/cwtch.dart';
|
|||
import '../config.dart';
|
||||
|
||||
import "package:path/path.dart" show dirname, join;
|
||||
import 'dart:io' show Platform;
|
||||
|
||||
/////////////////////
|
||||
/// Cwtch API ///
|
||||
|
@ -270,6 +272,14 @@ class CwtchFfi implements Cwtch {
|
|||
return _cwtchDir;
|
||||
}
|
||||
|
||||
// ignore: non_constant_identifier_names
|
||||
Future<void> ReconnectCwtchForeground() async {
|
||||
var reconnectCwtch = library.lookup<NativeFunction<Void Function()>>("c_ReconnectCwtchForeground");
|
||||
// ignore: non_constant_identifier_names
|
||||
final ReconnectCwtchForeground = reconnectCwtch.asFunction<void Function()>();
|
||||
ReconnectCwtchForeground();
|
||||
}
|
||||
|
||||
// Called on object being disposed to (presumably on app close) to close the isolate that's listening to libcwtch-go events
|
||||
@override
|
||||
void dispose() {
|
||||
|
|
|
@ -77,7 +77,7 @@ class CwtchGomobile implements Cwtch {
|
|||
Future<void> Start() async {
|
||||
print("gomobile.dart: Start()...");
|
||||
androidHomeDirectoryStr = (await androidHomeDirectory).path;
|
||||
_cwtchDir = path.join(androidHomeDirectoryStr, ".cwtch");
|
||||
_cwtchDir = path.join(await androidHomeDirectoryStr, ".cwtch");
|
||||
if (EnvironmentConfig.BUILD_VER == dev_version) {
|
||||
_cwtchDir = path.join(_cwtchDir, "dev");
|
||||
}
|
||||
|
@ -86,6 +86,12 @@ class CwtchGomobile implements Cwtch {
|
|||
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
|
||||
Future<void> _handleAppbusEvent(MethodCall call) async {
|
||||
final String json = call.arguments;
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
{
|
||||
"@@locale": "cy",
|
||||
"@@last_modified": "2024-02-12T08:05:24+01:00",
|
||||
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
|
||||
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
|
||||
"@@last_modified": "2024-02-08T10:33:11+01:00",
|
||||
"settingsImportThemeButton": "Import Theme",
|
||||
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
|
||||
"settingsImportThemeTitle": "Import Theme",
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
{
|
||||
"@@locale": "da",
|
||||
"@@last_modified": "2024-02-12T08:05:24+01:00",
|
||||
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
|
||||
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
|
||||
"@@last_modified": "2024-02-08T10:33:11+01:00",
|
||||
"settingsImportThemeButton": "Import Theme",
|
||||
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
|
||||
"settingsImportThemeTitle": "Import Theme",
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
{
|
||||
"@@locale": "de",
|
||||
"@@last_modified": "2024-02-12T08:05:24+01:00",
|
||||
"settingsExperimentsShowPerformanceTitle": "Leistungs-Overlay anzeigen",
|
||||
"settingsExperimentsShowPerformanceDescription": "Zeigt ein Overlay-Diagramm der Renderzeit an.",
|
||||
"@@last_modified": "2024-02-08T10:33:11+01:00",
|
||||
"defaultScalingText": "Text in Standardgröße (Skalierungsfaktor:",
|
||||
"deleteServerConfirmBtn": "Server wirklich löschen",
|
||||
"groupsOnThisServerLabel": "Gruppen, in denen ich bin, werden auf diesem Server gehostet",
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
{
|
||||
"@@locale": "el",
|
||||
"@@last_modified": "2024-02-12T08:05:24+01:00",
|
||||
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
|
||||
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
|
||||
"@@last_modified": "2024-02-08T10:33:11+01:00",
|
||||
"settingsImportThemeButton": "Import Theme",
|
||||
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
|
||||
"settingsImportThemeTitle": "Import Theme",
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
{
|
||||
"@@locale": "en",
|
||||
"@@last_modified": "2024-02-12T08:05:24+01:00",
|
||||
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
|
||||
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
|
||||
"@@last_modified": "2024-02-08T10:33:11+01:00",
|
||||
"settingThemeOverwriteConfirm": "Confirm",
|
||||
"settingThemeOverwriteQuestion": "Theme $themeName already exists, confirm overwrite?",
|
||||
"settingsThemeErrorInvalid": "Error: Could not import $themeName, theme.yml missing, not a theme directory",
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
{
|
||||
"@@locale": "es",
|
||||
"@@last_modified": "2024-02-12T08:05:24+01:00",
|
||||
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
|
||||
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
|
||||
"@@last_modified": "2024-02-08T10:33:11+01:00",
|
||||
"settingsImportThemeButton": "Import Theme",
|
||||
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
|
||||
"settingsImportThemeTitle": "Import Theme",
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
{
|
||||
"@@locale": "fr",
|
||||
"@@last_modified": "2024-02-12T08:05:24+01:00",
|
||||
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
|
||||
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
|
||||
"@@last_modified": "2024-02-08T10:33:11+01:00",
|
||||
"settingsImportThemeButton": "Import Theme",
|
||||
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
|
||||
"settingsImportThemeTitle": "Import Theme",
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
{
|
||||
"@@locale": "it",
|
||||
"@@last_modified": "2024-02-12T08:05:24+01:00",
|
||||
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
|
||||
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
|
||||
"@@last_modified": "2024-02-08T10:33:11+01:00",
|
||||
"settingsImportThemeButton": "Import Theme",
|
||||
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
|
||||
"settingsImportThemeTitle": "Import Theme",
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
{
|
||||
"@@locale": "ja",
|
||||
"@@last_modified": "2024-02-12T08:05:24+01:00",
|
||||
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
|
||||
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
|
||||
"@@last_modified": "2024-02-08T10:33:11+01:00",
|
||||
"settingsImportThemeButton": "Import Theme",
|
||||
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
|
||||
"settingsImportThemeTitle": "Import Theme",
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
{
|
||||
"@@locale": "ko",
|
||||
"@@last_modified": "2024-02-12T08:05:24+01:00",
|
||||
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
|
||||
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
|
||||
"@@last_modified": "2024-02-08T10:33:11+01:00",
|
||||
"sendAnInvitation": "초대를 보냈습니다: ",
|
||||
"sendInvite": "연락처 또는 그룹 초대 보내기",
|
||||
"pasteAddressToAddContact": "Paste a cwtch address, invitation or key bundle here to add a new conversation",
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
{
|
||||
"@@locale": "lb",
|
||||
"@@last_modified": "2024-02-12T08:05:24+01:00",
|
||||
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
|
||||
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
|
||||
"@@last_modified": "2024-02-08T10:33:11+01:00",
|
||||
"settingsImportThemeButton": "Import Theme",
|
||||
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
|
||||
"settingsImportThemeTitle": "Import Theme",
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
{
|
||||
"@@locale": "nl",
|
||||
"@@last_modified": "2024-02-12T08:05:24+01:00",
|
||||
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
|
||||
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
|
||||
"@@last_modified": "2024-02-08T10:33:11+01:00",
|
||||
"settingsImportThemeButton": "Import Theme",
|
||||
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
|
||||
"settingsImportThemeTitle": "Import Theme",
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
{
|
||||
"@@locale": "no",
|
||||
"@@last_modified": "2024-02-12T08:05:24+01:00",
|
||||
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
|
||||
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
|
||||
"@@last_modified": "2024-02-08T10:33:11+01:00",
|
||||
"settingsImportThemeButton": "Import Theme",
|
||||
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
|
||||
"settingsImportThemeTitle": "Import Theme",
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
{
|
||||
"@@locale": "pl",
|
||||
"@@last_modified": "2024-02-12T08:05:24+01:00",
|
||||
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
|
||||
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
|
||||
"@@last_modified": "2024-02-08T10:33:11+01:00",
|
||||
"settingsImportThemeButton": "Import Theme",
|
||||
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
|
||||
"settingsImportThemeTitle": "Import Theme",
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
{
|
||||
"@@locale": "pt",
|
||||
"@@last_modified": "2024-02-12T08:05:24+01:00",
|
||||
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
|
||||
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
|
||||
"@@last_modified": "2024-02-08T10:33:11+01:00",
|
||||
"settingsImportThemeButton": "Import Theme",
|
||||
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
|
||||
"settingsImportThemeTitle": "Import Theme",
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
{
|
||||
"@@locale": "pt_BR",
|
||||
"@@last_modified": "2024-02-12T08:05:24+01:00",
|
||||
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
|
||||
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
|
||||
"@@last_modified": "2024-02-08T10:33:11+01:00",
|
||||
"settingsImportThemeButton": "Import Theme",
|
||||
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
|
||||
"settingsImportThemeTitle": "Import Theme",
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
{
|
||||
"@@locale": "ro",
|
||||
"@@last_modified": "2024-02-12T08:05:24+01:00",
|
||||
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
|
||||
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
|
||||
"@@last_modified": "2024-02-08T10:33:11+01:00",
|
||||
"settingsImportThemeButton": "Import Theme",
|
||||
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
|
||||
"settingsImportThemeTitle": "Import Theme",
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
{
|
||||
"@@locale": "ru",
|
||||
"@@last_modified": "2024-02-12T08:05:24+01:00",
|
||||
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
|
||||
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
|
||||
"@@last_modified": "2024-02-08T10:33:11+01:00",
|
||||
"settingsImportThemeButton": "Import Theme",
|
||||
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
|
||||
"settingsImportThemeTitle": "Import Theme",
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
{
|
||||
"@@locale": "sk",
|
||||
"@@last_modified": "2024-02-12T08:05:24+01:00",
|
||||
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
|
||||
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
|
||||
"@@last_modified": "2024-02-08T10:33:11+01:00",
|
||||
"settingsImportThemeButton": "Import Theme",
|
||||
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
|
||||
"settingsImportThemeTitle": "Import Theme",
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
{
|
||||
"@@locale": "sv",
|
||||
"@@last_modified": "2024-02-12T08:05:24+01:00",
|
||||
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
|
||||
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
|
||||
"@@last_modified": "2024-02-08T10:33:11+01:00",
|
||||
"settingsImportThemeButton": "Import Theme",
|
||||
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
|
||||
"settingsImportThemeTitle": "Import Theme",
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
{
|
||||
"@@locale": "sw",
|
||||
"@@last_modified": "2024-02-12T08:05:24+01:00",
|
||||
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
|
||||
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
|
||||
"@@last_modified": "2024-02-08T10:33:11+01:00",
|
||||
"settingsImportThemeButton": "Import Theme",
|
||||
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
|
||||
"settingsImportThemeTitle": "Import Theme",
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
{
|
||||
"@@locale": "tr",
|
||||
"@@last_modified": "2024-02-12T08:05:24+01:00",
|
||||
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
|
||||
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
|
||||
"@@last_modified": "2024-02-08T10:33:11+01:00",
|
||||
"settingsImportThemeButton": "Import Theme",
|
||||
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
|
||||
"settingsImportThemeTitle": "Import Theme",
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
{
|
||||
"@@locale": "uk",
|
||||
"@@last_modified": "2024-02-12T08:05:24+01:00",
|
||||
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
|
||||
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
|
||||
"@@last_modified": "2024-02-08T10:33:11+01:00",
|
||||
"settingsImportThemeButton": "Import Theme",
|
||||
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
|
||||
"settingsImportThemeTitle": "Import Theme",
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
{
|
||||
"@@locale": "uz",
|
||||
"@@last_modified": "2024-02-12T08:05:24+01:00",
|
||||
"settingsExperimentsShowPerformanceDescription": "Display an overlay graph of render time.",
|
||||
"settingsExperimentsShowPerformanceTitle": "Show Performance Overlay",
|
||||
"@@last_modified": "2024-02-08T10:33:11+01:00",
|
||||
"settingsImportThemeButton": "Import Theme",
|
||||
"settingsImportThemeDescription": "Select theme directory to import for use in Cwtch",
|
||||
"settingsImportThemeTitle": "Import Theme",
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:isolate';
|
||||
import 'package:cwtch/config.dart';
|
||||
import 'package:cwtch/notification_manager.dart';
|
||||
import 'package:cwtch/themes/cwtch.dart';
|
||||
import 'package:cwtch/views/doublecolview.dart';
|
||||
import 'package:cwtch/views/messageview.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: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 globalTorStatus = TorStatus();
|
||||
var globalAppState = AppState();
|
||||
|
@ -76,7 +80,7 @@ class FlwtchState extends State<Flwtch> with WindowListener {
|
|||
@override
|
||||
initState() {
|
||||
print("initState() started, setting up handlers");
|
||||
globalSettings = Settings(Locale("en", ''));
|
||||
globalSettings = Settings(Locale("en", ''), CwtchDark());
|
||||
globalErrorHandler = ErrorHandler();
|
||||
globalTorStatus = TorStatus();
|
||||
globalAppState = AppState();
|
||||
|
@ -103,14 +107,11 @@ class FlwtchState extends State<Flwtch> with WindowListener {
|
|||
new CwtchNotifier(profs, globalSettings, globalErrorHandler, globalTorStatus, newDesktopNotificationsManager(_notificationSelectConvo), globalAppState, globalServersList, this);
|
||||
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
|
||||
Future.delayed(const Duration(milliseconds: 100), () {
|
||||
print("initState delayed: invoking cwtch.Start()");
|
||||
cwtch.Start().then((v) {
|
||||
cwtch.getCwtchDir().then((dir) {
|
||||
globalSettings.themeloader.LoadThemes(dir);
|
||||
});
|
||||
});
|
||||
Future.delayed(const Duration(milliseconds: 50), () async {
|
||||
await cwtch.Start();
|
||||
LoadThemes(await cwtch.getCwtchDir());
|
||||
});
|
||||
print("initState: starting connectivityListener");
|
||||
if (EnvironmentConfig.TEST_MODE == false) {
|
||||
|
@ -127,7 +128,7 @@ class FlwtchState extends State<Flwtch> with WindowListener {
|
|||
// gracefully fails and NOPs, as it's not a required functionality
|
||||
startConnectivityListener() async {
|
||||
try {
|
||||
connectivityStream = Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {
|
||||
connectivityStream = await Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {
|
||||
// Got a new connectivity status!
|
||||
if (result == ConnectivityResult.none) {
|
||||
connectivityState = ConnectivityState.confirmed_offline;
|
||||
|
@ -160,7 +161,6 @@ class FlwtchState extends State<Flwtch> with WindowListener {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
globalSettings.initPackageInfo();
|
||||
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
getFlwtchStateProvider(),
|
||||
|
@ -172,6 +172,10 @@ class FlwtchState extends State<Flwtch> with WindowListener {
|
|||
getServerListStateProvider(),
|
||||
],
|
||||
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>(
|
||||
builder: (context, settings, appState, child) => MaterialApp(
|
||||
key: Key('app'),
|
||||
|
@ -189,7 +193,7 @@ class FlwtchState extends State<Flwtch> with WindowListener {
|
|||
title: 'Cwtch',
|
||||
showSemanticsDebugger: settings.useSemanticDebugger,
|
||||
theme: mkThemeData(settings),
|
||||
home: (!appState.loaded) ? SplashView() : ProfileMgrView(),
|
||||
home: (!appState.cwtchInit || appState.modalState != ModalState.none) || !cwtch.IsLoaded() ? SplashView() : ProfileMgrView(),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
@ -252,6 +256,7 @@ class FlwtchState extends State<Flwtch> with WindowListener {
|
|||
exit(0);
|
||||
}
|
||||
}
|
||||
;
|
||||
}
|
||||
|
||||
// Invoked via notificationClickChannel by MyBroadcastReceiver in MainActivity.kt
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:cwtch/themes/cwtch.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -7,14 +8,16 @@ import 'package:glob/list_local_fs.dart';
|
|||
import 'config.dart';
|
||||
import 'licenses.dart';
|
||||
import 'main.dart';
|
||||
import 'themes/opaque.dart';
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
import "package:flutter_driver/driver_extension.dart";
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:glob/glob.dart';
|
||||
|
||||
var globalSettings = Settings(Locale("en", ''));
|
||||
var globalSettings = Settings(Locale("en", ''), CwtchDark());
|
||||
var globalErrorHandler = ErrorHandler();
|
||||
|
||||
Future<void> main() async {
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:cwtch/config.dart';
|
||||
import 'package:cwtch/main.dart';
|
||||
import 'package:cwtch/third_party/miniaudio/lib/miniaudio.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
enum ModalState { none, storageMigration, shutdown }
|
||||
|
@ -18,8 +19,6 @@ class AppState extends ChangeNotifier {
|
|||
bool _unreadMessagesBelow = false;
|
||||
bool _disableFilePicker = false;
|
||||
bool _focus = true;
|
||||
bool _settingsLoaded = false;
|
||||
bool _themesLoaded = false;
|
||||
|
||||
StreamController<bool> _profilesUnreadNotifyControler = StreamController<bool>();
|
||||
late Stream<bool> profilesUnreadNotify;
|
||||
|
@ -30,18 +29,22 @@ class AppState extends ChangeNotifier {
|
|||
|
||||
void SetCwtchInit() {
|
||||
cwtchInit = true;
|
||||
var audio = MiniAudio();
|
||||
audio.initAudio().then((value) {
|
||||
audio.playAudio("assets/sounds_online.wav");
|
||||
});
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void SetAppError(String error) {
|
||||
appError = error;
|
||||
EnvironmentConfig.debugLog("App Error: $appError");
|
||||
EnvironmentConfig.debugLog("App Error: ${appError}");
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void SetModalState(ModalState newState) {
|
||||
modalState = newState;
|
||||
EnvironmentConfig.debugLog("Modal State: $newState");
|
||||
EnvironmentConfig.debugLog("Modal State: ${newState}");
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
|
@ -88,18 +91,6 @@ class AppState extends ChangeNotifier {
|
|||
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;
|
||||
|
||||
void notifyProfileUnread() {
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:ffi';
|
||||
|
||||
import 'package:cwtch/config.dart';
|
||||
import 'package:cwtch/main.dart';
|
||||
import 'package:cwtch/models/message_draft.dart';
|
||||
import 'package:cwtch/models/profile.dart';
|
||||
|
@ -5,12 +9,14 @@ import 'package:cwtch/models/redaction.dart';
|
|||
import 'package:cwtch/themes/opaque.dart';
|
||||
import 'package:cwtch/views/contactsview.dart';
|
||||
import 'package:cwtch/widgets/messagerow.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
|
||||
|
||||
import 'message.dart';
|
||||
import 'messagecache.dart';
|
||||
|
||||
enum ConversationNotificationPolicy {
|
||||
|
@ -130,6 +136,14 @@ class ContactInfoState extends ChangeNotifier {
|
|||
MessageDraft get messageDraft => this._messageDraft;
|
||||
|
||||
DateTime get lastRetryTime => this._lastRetryTime;
|
||||
|
||||
Uint8List _vid = Uint8List(0);
|
||||
Uint8List get vid => _vid;
|
||||
set vid(data) {
|
||||
this._vid = data;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
set lastRetryTime(DateTime lastRetryTime) {
|
||||
this._lastRetryTime = lastRetryTime;
|
||||
notifyListeners();
|
||||
|
|
|
@ -54,7 +54,7 @@ class ContactListState extends ChangeNotifier {
|
|||
if (otherGroups != null && otherGroups.isNotEmpty) {
|
||||
EnvironmentConfig.debugLog("sharing antispam tickets to new group. FIXME: in Cwtch 1.14");
|
||||
var antispamTickets = otherGroups[0].antispamTickets;
|
||||
_contacts.last.antispamTickets = antispamTickets;
|
||||
_contacts.last!.antispamTickets = antispamTickets;
|
||||
}
|
||||
servers?.addGroup(newContact);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ const QuotedMessageOverlay = 10;
|
|||
const SuggestContactOverlay = 100;
|
||||
const InviteGroupOverlay = 101;
|
||||
const FileShareOverlay = 200;
|
||||
|
||||
const VideoOverlay = 0xF07;
|
||||
// Defines the length of the tor v3 onion address. Code using this constant will
|
||||
// need to updated when we allow multiple different identifiers. At which time
|
||||
// it will likely be prudent to define a proper Contact wrapper.
|
||||
|
@ -64,7 +64,6 @@ Message compileOverlay(MessageInfo messageInfo) {
|
|||
|
||||
abstract class CacheHandler {
|
||||
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 {
|
||||
|
@ -129,8 +128,7 @@ class ByIndex implements CacheHandler {
|
|||
List<dynamic> messagesWrapper = jsonDecode(msgs);
|
||||
|
||||
for (; i < messagesWrapper.length; i++) {
|
||||
var messageInfo = MessageWrapperToInfo(profileOnion, conversationIdentifier, messagesWrapper[i]);
|
||||
messageInfo.metadata.lastChecked = DateTime.now();
|
||||
var messageInfo = messageWrapperToInfo(profileOnion, conversationIdentifier, messagesWrapper[i]);
|
||||
cache.addIndexed(messageInfo, start + i);
|
||||
}
|
||||
} catch (e, stacktrace) {
|
||||
|
@ -145,13 +143,6 @@ class ByIndex implements CacheHandler {
|
|||
void add(MessageCache cache, MessageInfo messageInfo) {
|
||||
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 {
|
||||
|
@ -181,11 +172,6 @@ class ById implements CacheHandler {
|
|||
}
|
||||
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 {
|
||||
|
@ -214,11 +200,6 @@ class ByContentHash implements CacheHandler {
|
|||
}
|
||||
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) {
|
||||
|
@ -276,16 +257,6 @@ Future<Message> messageHandler(BuildContext context, String profileOnion, int co
|
|||
|
||||
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) {
|
||||
return compileOverlay(messageInfo);
|
||||
} else {
|
||||
|
@ -301,14 +272,14 @@ MessageInfo? messageJsonToInfo(String profileOnion, int conversationIdentifier,
|
|||
return null;
|
||||
}
|
||||
|
||||
return MessageWrapperToInfo(profileOnion, conversationIdentifier, messageWrapper);
|
||||
return messageWrapperToInfo(profileOnion, conversationIdentifier, messageWrapper);
|
||||
} catch (e, stacktrace) {
|
||||
EnvironmentConfig.debugLog("message handler exception on parse message and cache: " + e.toString() + " " + stacktrace.toString());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
MessageInfo MessageWrapperToInfo(String profileOnion, int conversationIdentifier, dynamic messageWrapper) {
|
||||
MessageInfo messageWrapperToInfo(String profileOnion, int conversationIdentifier, dynamic messageWrapper) {
|
||||
// Construct the initial metadata
|
||||
var messageID = messageWrapper['ID'];
|
||||
var timestamp = DateTime.tryParse(messageWrapper['Timestamp'])!;
|
||||
|
@ -341,7 +312,6 @@ class MessageMetadata extends ChangeNotifier {
|
|||
|
||||
final String? signature;
|
||||
final String contenthash;
|
||||
DateTime? lastChecked;
|
||||
|
||||
dynamic get attributes => this._attributes;
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
/// A "MessageDraft" structure that stores information about in-progress message drafts.
|
||||
/// MessageDraft stores text, quoted replies, and attached images.
|
||||
|
@ -49,8 +50,6 @@ class MessageDraft extends ChangeNotifier {
|
|||
void clearDraft() {
|
||||
this._quotedReference = null;
|
||||
this.ctrlCompose.clear();
|
||||
this.ctrlCompose.clearComposing();
|
||||
this.ctrlCompose.text = "";
|
||||
this._inviteHandle = null;
|
||||
notifyListeners();
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
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));
|
||||
if (contenthash != "") {
|
||||
if (contenthash != null && contenthash != "") {
|
||||
this.cacheByHash[contenthash] = messageID;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
import 'package:cwtch/third_party/base85/base_85_encoder.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import '../../third_party/base85/base_85_codec.dart';
|
||||
|
||||
class VidMessage {
|
||||
final int o;
|
||||
final Uint8List d;
|
||||
DateTime? s;
|
||||
DateTime? r;
|
||||
DateTime? t;
|
||||
|
||||
VidMessage({required this.o, required this.d});
|
||||
|
||||
VidMessage.fromJson(Map<String, dynamic> json)
|
||||
: o = json['o'],
|
||||
d = Base85Codec.new().decode(json['d']),
|
||||
s = DateTime.tryParse(json['s'] ?? ""),
|
||||
t = DateTime.tryParse(json['t'] ?? ""),
|
||||
r = DateTime.tryParse(json['r'] ?? "");
|
||||
|
||||
Map<String, dynamic> toJson() => {'o': o, 'd': Base85Codec.new().encode(d), 's': DateTime.now().toUtc().toIso8601String()};
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:cwtch/config.dart';
|
||||
import 'package:cwtch/models/message.dart';
|
||||
import 'package:cwtch/models/messages/malformedmessage.dart';
|
||||
import 'package:cwtch/widgets/malformedbubble.dart';
|
||||
|
@ -10,6 +11,7 @@ import 'package:flutter/widgets.dart';
|
|||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../../settings.dart';
|
||||
import '../../third_party/linkify/flutter_linkify.dart';
|
||||
|
||||
class QuotedMessageStructure {
|
||||
final String quotedHash;
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
import 'dart:math';
|
||||
|
||||
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/messageloadingbubble.dart';
|
||||
import 'package:cwtch/widgets/messagerow.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../../settings.dart';
|
||||
import '../../third_party/linkify/flutter_linkify.dart';
|
||||
import '../../widgets/messageBubbleWidgetHelpers.dart';
|
||||
|
||||
class TextMessage extends Message {
|
||||
|
@ -21,6 +27,7 @@ class TextMessage extends Message {
|
|||
builder: (bcontext, child) {
|
||||
var formatMessages = Provider.of<Settings>(bcontext).isExperimentEnabled(FormattingExperiment);
|
||||
return compileMessageContentWidget(context, constraints ?? BoxConstraints.loose(MediaQuery.sizeOf(context)), false, content, FocusNode(), formatMessages, false);
|
||||
;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,8 @@ import '../views/contactsview.dart';
|
|||
import 'contact.dart';
|
||||
import 'contactlist.dart';
|
||||
import 'filedownloadprogress.dart';
|
||||
import 'message.dart';
|
||||
import 'messagecache.dart';
|
||||
import 'profileservers.dart';
|
||||
|
||||
class ProfileInfoState extends ChangeNotifier {
|
||||
|
@ -239,7 +241,7 @@ class ProfileInfoState extends ChangeNotifier {
|
|||
this._unreadMessages = 0;
|
||||
this.replaceServers(serverJson);
|
||||
|
||||
if (contactsJson != "" && contactsJson != "null") {
|
||||
if (contactsJson != null && contactsJson != "" && contactsJson != "null") {
|
||||
List<dynamic> contacts = jsonDecode(contactsJson);
|
||||
contacts.forEach((contact) {
|
||||
var profileContact = this._contacts.getContact(contact["identifier"]);
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
import 'dart:ui';
|
||||
|
||||
import 'package:cwtch/config.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:cwtch/config.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
import 'contact.dart';
|
||||
|
|
|
@ -3,8 +3,13 @@ import 'dart:convert';
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:cwtch/main.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:win_toast/win_toast.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;
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import 'dart:collection';
|
||||
import 'dart:ui';
|
||||
import 'dart:core';
|
||||
|
||||
import 'package:cwtch/themes/cwtch.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
|
||||
|
@ -40,6 +42,7 @@ enum NotificationContent {
|
|||
class Settings extends ChangeNotifier {
|
||||
Locale locale;
|
||||
late PackageInfo packageInfo;
|
||||
OpaqueThemeType theme;
|
||||
bool _themeImages = false;
|
||||
|
||||
// explicitly set experiments to false until told otherwise...
|
||||
|
@ -67,8 +70,6 @@ class Settings extends ChangeNotifier {
|
|||
bool _useSemanticDebugger = false;
|
||||
double _fontScaling = 1.0;
|
||||
|
||||
ThemeLoader themeloader = ThemeLoader();
|
||||
|
||||
String get torCacheDir => _torCacheDir;
|
||||
|
||||
// Whether to show the profiling interface, not saved
|
||||
|
@ -87,13 +88,8 @@ class Settings extends ChangeNotifier {
|
|||
|
||||
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) {
|
||||
_themeId = themeId;
|
||||
_mode = mode;
|
||||
theme = getTheme(themeId, mode);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
|
@ -408,12 +404,9 @@ class Settings extends ChangeNotifier {
|
|||
// 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)
|
||||
bool shouldPreview(String path) {
|
||||
return isExperimentEnabled(ImagePreviewsExperiment) && isImage(path);
|
||||
}
|
||||
|
||||
bool isImage(String path) {
|
||||
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;
|
||||
|
@ -468,7 +461,7 @@ class Settings extends ChangeNotifier {
|
|||
}
|
||||
|
||||
/// Construct a default settings object.
|
||||
Settings(this.locale);
|
||||
Settings(this.locale, this.theme);
|
||||
|
||||
String _blodeuweddPath = "";
|
||||
String get blodeuweddPath => _blodeuweddPath;
|
||||
|
@ -482,7 +475,7 @@ class Settings extends ChangeNotifier {
|
|||
dynamic asJson() {
|
||||
return {
|
||||
"Locale": this.locale.toString(),
|
||||
"Theme": _themeId,
|
||||
"Theme": theme.theme,
|
||||
"ThemeMode": theme.mode,
|
||||
"ThemeImages": _themeImages,
|
||||
"PreviousPid": -1,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'dart:io';
|
||||
import 'dart:ui';
|
||||
import 'dart:core';
|
||||
|
||||
import 'package:cwtch/themes/cwtch.dart';
|
||||
|
@ -15,50 +16,41 @@ const mode_dark = "dark";
|
|||
|
||||
final TextStyle defaultSmallTextStyle = TextStyle(fontFamily: "Inter", fontWeight: FontWeight.normal, fontSize: 10);
|
||||
final TextStyle defaultMessageTextStyle = TextStyle(fontFamily: "Inter", fontWeight: FontWeight.w400, fontSize: 13, fontFamilyFallback: [Platform.isWindows ? 'Segoe UI Emoji' : "Noto Color Emoji"]);
|
||||
final TextStyle defaultFormLabelTextStyle = TextStyle(
|
||||
fontFamily: "Inter",
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 20,
|
||||
);
|
||||
final TextStyle defaultFormLabelTextStyle = TextStyle(fontFamily: "Inter", fontWeight: FontWeight.bold, fontSize: 20);
|
||||
final TextStyle defaultTextStyle = TextStyle(fontFamily: "Inter", fontWeight: FontWeight.w500, fontSize: 12);
|
||||
final TextStyle defaultTextButtonStyle = defaultTextStyle.copyWith(fontWeight: FontWeight.bold);
|
||||
final TextStyle defaultDropDownMenuItemTextStyle = TextStyle(fontFamily: "Inter", fontWeight: FontWeight.bold, fontSize: 16);
|
||||
|
||||
class ThemeLoader extends ChangeNotifier {
|
||||
Map<String, Map<String, OpaqueThemeType>> themes = Map();
|
||||
Map<String, Map<String, OpaqueThemeType>> themes = Map();
|
||||
|
||||
LoadThemes(String cwtchDir) async {
|
||||
themes.clear(); // clear themes...
|
||||
loadBuiltinThemes().then((builtinThemes) {
|
||||
themes.addAll(builtinThemes);
|
||||
notifyListeners();
|
||||
loadCustomThemes(path.join(cwtchDir, custom_themes_subdir)).then((customThemes) {
|
||||
themes.addAll(customThemes);
|
||||
notifyListeners();
|
||||
});
|
||||
});
|
||||
LoadThemes(String cwtchDir) async {
|
||||
themes = await loadBuiltinThemes();
|
||||
final customThemes = await loadCustomThemes(path.join(cwtchDir, custom_themes_subdir));
|
||||
themes.addAll(customThemes);
|
||||
}
|
||||
|
||||
OpaqueThemeType getTheme(String themeId, String mode) {
|
||||
if (themeId == "") {
|
||||
themeId = cwtch_theme;
|
||||
}
|
||||
if (themeId == mode_light) {
|
||||
themeId = cwtch_theme;
|
||||
mode = mode_light;
|
||||
}
|
||||
if (themeId == mode_dark) {
|
||||
themeId = cwtch_theme;
|
||||
mode = mode_dark;
|
||||
}
|
||||
|
||||
OpaqueThemeType getTheme(String? themeId, String? mode) {
|
||||
if (themeId == null) {
|
||||
themeId = cwtch_theme;
|
||||
}
|
||||
if (themeId == mode_light) {
|
||||
mode = mode_light;
|
||||
}
|
||||
if (themeId == mode_dark) {
|
||||
mode = mode_dark;
|
||||
}
|
||||
var theme = themes[themeId]?[mode] ?? themes[themeId]?[flipMode(mode ?? mode_dark)];
|
||||
return theme ?? CwtchDark();
|
||||
}
|
||||
var theme = themes[themeId]?[mode] ?? themes[themeId]?[flipMode(mode)];
|
||||
return theme ?? CwtchDark();
|
||||
}
|
||||
|
||||
String flipMode(String mode) {
|
||||
if (mode == mode_dark) {
|
||||
return mode_light;
|
||||
}
|
||||
return mode_dark;
|
||||
String flipMode(String mode) {
|
||||
if (mode == mode_dark) {
|
||||
return mode_light;
|
||||
}
|
||||
return mode_dark;
|
||||
}
|
||||
|
||||
Color lighten(Color color, [double amount = 0.15]) {
|
||||
|
@ -180,22 +172,18 @@ ThemeData mkThemeData(Settings opaque) {
|
|||
return ThemeData(
|
||||
hoverColor: opaque.current().backgroundHilightElementColor.withOpacity(0.5),
|
||||
visualDensity: VisualDensity.adaptivePlatformDensity,
|
||||
primarySwatch: getMaterialColor(opaque.current().topbarColor),
|
||||
primaryIconTheme: IconThemeData(
|
||||
color: opaque.current().mainTextColor,
|
||||
),
|
||||
primaryColor: opaque.current().mainTextColor,
|
||||
canvasColor: opaque.current().backgroundMainColor,
|
||||
backgroundColor: opaque.current().backgroundMainColor,
|
||||
highlightColor: opaque.current().hilightElementColor,
|
||||
iconTheme: IconThemeData(
|
||||
color: opaque.current().toolbarIconColor,
|
||||
),
|
||||
cardColor: opaque.current().backgroundMainColor,
|
||||
bottomSheetTheme: BottomSheetThemeData(
|
||||
backgroundColor: opaque.current().backgroundPaneColor,
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: double.infinity,
|
||||
),
|
||||
),
|
||||
appBarTheme: AppBarTheme(
|
||||
systemOverlayStyle: SystemUiOverlayStyle(
|
||||
// Status bar color
|
||||
|
@ -212,9 +200,7 @@ ThemeData mkThemeData(Settings opaque) {
|
|||
actionsIconTheme: IconThemeData(
|
||||
color: opaque.current().mainTextColor,
|
||||
)),
|
||||
listTileTheme: ListTileThemeData(
|
||||
titleTextStyle: defaultFormLabelTextStyle.copyWith(color: opaque.current().mainTextColor), subtitleTextStyle: defaultMessageTextStyle.copyWith(color: opaque.current().mainTextColor)),
|
||||
iconButtonTheme: IconButtonThemeData(style: ButtonStyle(textStyle: MaterialStateProperty.all(defaultFormLabelTextStyle))),
|
||||
|
||||
//bottomNavigationBarTheme: BottomNavigationBarThemeData(type: BottomNavigationBarType.fixed, backgroundColor: opaque.current().backgroundHilightElementColor), // Can't determine current use
|
||||
textButtonTheme: TextButtonThemeData(
|
||||
style: ButtonStyle(
|
||||
|
@ -243,12 +229,12 @@ ThemeData mkThemeData(Settings opaque) {
|
|||
),
|
||||
scrollbarTheme: ScrollbarThemeData(thumbVisibility: MaterialStateProperty.all(false), thumbColor: MaterialStateProperty.all(opaque.current().scrollbarDefaultColor)),
|
||||
tabBarTheme: TabBarTheme(
|
||||
labelColor: opaque.current().mainTextColor,
|
||||
unselectedLabelColor: opaque.current().mainTextColor,
|
||||
indicator: UnderlineTabIndicator(borderSide: BorderSide(color: opaque.current().defaultButtonActiveColor)),
|
||||
labelStyle: opaque.scaleFonts(defaultTextButtonStyle).copyWith(color: opaque.current().mainTextColor),
|
||||
unselectedLabelStyle: opaque.scaleFonts(defaultTextStyle).copyWith(color: opaque.current().mainTextColor),
|
||||
tabAlignment: TabAlignment.center),
|
||||
labelColor: opaque.current().mainTextColor,
|
||||
unselectedLabelColor: opaque.current().mainTextColor,
|
||||
indicator: UnderlineTabIndicator(borderSide: BorderSide(color: opaque.current().defaultButtonActiveColor)),
|
||||
labelStyle: opaque.scaleFonts(defaultTextButtonStyle),
|
||||
unselectedLabelStyle: opaque.scaleFonts(defaultTextStyle),
|
||||
),
|
||||
dialogTheme: DialogTheme(
|
||||
backgroundColor: opaque.current().backgroundPaneColor,
|
||||
titleTextStyle: TextStyle(fontFamily: "Inter", fontWeight: FontWeight.bold, color: opaque.current().mainTextColor),
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:cwtch/config.dart';
|
||||
import 'package:cwtch/themes/cwtch.dart';
|
||||
import 'package:cwtch/themes/opaque.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:glob/list_local_fs.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:yaml/yaml.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
@ -129,7 +132,7 @@ class YmlTheme extends OpaqueThemeType {
|
|||
val = yml["themes"][mode]["theme"][val] ?? val;
|
||||
}
|
||||
if (!(val is int)) {
|
||||
val = yml["themes"][mode]?["colors"]?[val] ?? val;
|
||||
val = yml["themes"][mode]?["colors"][val] ?? val;
|
||||
}
|
||||
if (!(val is int)) {
|
||||
val = yml["colors"]?[val];
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 51d8c18dd869702fbef77ce574493078a2acf54d
|
|
@ -0,0 +1,31 @@
|
|||
## 0.0.1
|
||||
|
||||
* Initial release.
|
||||
|
||||
## 0.0.2
|
||||
|
||||
* Fixes in core API.
|
||||
|
||||
## 0.0.3
|
||||
|
||||
* Created API for storing frame into Base64 Image.
|
||||
|
||||
## 0.0.4
|
||||
|
||||
* Code refractor
|
||||
|
||||
## 0.0.5
|
||||
|
||||
* Converted API functions into asyc functions.
|
||||
|
||||
## 0.0.6
|
||||
|
||||
* Dart SDK version changed to 3.1.0
|
||||
|
||||
## 0.0.7
|
||||
|
||||
* OpenCV Dependencies added statically
|
||||
|
||||
## 0.0.8
|
||||
|
||||
* OpenCV static dependencies removed
|
|
@ -0,0 +1,60 @@
|
|||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2023, Open Privacy Research Society
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----
|
||||
Original License Follows...
|
||||
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2023, Muhammad Islam
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,93 @@
|
|||
# camera_linux
|
||||
|
||||
Camera Linux is a Flutter FFI plugin designed specifically for the Linux platform. This plugin allows Flutter developers to access and capture images from the Linux camera, seamlessly integrating native code invocation using Dart's FFI.
|
||||
|
||||
## Getting Started
|
||||
|
||||
Dart FFI Integration: Built on top of Flutter's FFI (Foreign Function Interface) to directly invoke native functions.
|
||||
Platform-Specific: Tailored for Linux, ensuring optimal performance and compatibility.
|
||||
Easy Access to Camera: Provides straightforward functions to capture images directly from the Linux camera.
|
||||
|
||||
## Project structure
|
||||
|
||||
This template uses the following structure:
|
||||
|
||||
* `src`: Contains the native source code, and a CmakeFile.txt file for building
|
||||
that source code into a dynamic library.
|
||||
|
||||
* `lib`: Contains the Dart code that defines the API of the plugin, and which
|
||||
calls into the native code using `dart:ffi`.
|
||||
|
||||
* platform folder (`linux`): Contains the build files
|
||||
for building and bundling the native code library with the platform application.
|
||||
|
||||
## Building and bundling native code
|
||||
|
||||
The `pubspec.yaml` specifies FFI plugins as follows:
|
||||
|
||||
```yaml
|
||||
plugin:
|
||||
platforms:
|
||||
some_platform:
|
||||
ffiPlugin: true
|
||||
```
|
||||
|
||||
This configuration invokes the native build for the various target platforms
|
||||
and bundles the binaries in Flutter applications using these FFI plugins.
|
||||
|
||||
This can be combined with dartPluginClass, such as when FFI is used for the
|
||||
implementation of one platform in a federated plugin:
|
||||
|
||||
```yaml
|
||||
plugin:
|
||||
implements: some_other_plugin
|
||||
platforms:
|
||||
some_platform:
|
||||
dartPluginClass: SomeClass
|
||||
ffiPlugin: true
|
||||
```
|
||||
|
||||
A plugin can have both FFI and method channels:
|
||||
|
||||
```yaml
|
||||
plugin:
|
||||
platforms:
|
||||
some_platform:
|
||||
pluginClass: SomeName
|
||||
ffiPlugin: true
|
||||
```
|
||||
|
||||
The native build systems that are invoked by FFI (and method channel) plugin is:
|
||||
|
||||
* For Linux and Windows: CMake.
|
||||
* See the documentation in linux/CMakeLists.txt.
|
||||
* See the documentation in windows/CMakeLists.txt.
|
||||
|
||||
## Binding to native code
|
||||
|
||||
Instead of manually writing the Dart bindings to native code, they are auto-generated from the header file (src/camera_linux.h) using the package:ffigen. To refresh these bindings, execute:
|
||||
|
||||
`flutter pub run ffigen --config ffigen.yaml`
|
||||
|
||||
## Invoking native code
|
||||
|
||||
Very short-running native functions can be directly invoked from any isolate.
|
||||
For example, see `sum` in `lib/camera_linux.dart`.
|
||||
|
||||
Longer-running functions should be invoked on a helper isolate to avoid
|
||||
dropping frames in Flutter applications.
|
||||
For example, see `sumAsync` in `lib/camera_linux.dart`.
|
||||
|
||||
## Getting Started with the Plugin
|
||||
|
||||
Add the camera_linux plugin to your pubspec.yaml:
|
||||
|
||||
```dependencies:
|
||||
camera_linux: ^0.1.0
|
||||
```
|
||||
|
||||
Execute the following command to fetch the package:
|
||||
`flutter pub get`
|
||||
|
||||
## Further Assistance
|
||||
For comprehensive guidance on Flutter, visit the official documentation, offering tutorials, samples, mobile development insights, and a complete API reference.
|
|
@ -0,0 +1,19 @@
|
|||
# Run with `flutter pub run ffigen --config ffigen.yaml`.
|
||||
name: CameraLinuxBindings
|
||||
description: |
|
||||
Bindings for `src/camera_linux.h`.
|
||||
|
||||
Regenerate bindings with `flutter pub run ffigen --config ffigen.yaml`.
|
||||
output: 'lib/camera_linux_bindings_generated.dart'
|
||||
headers:
|
||||
entry-points:
|
||||
- 'src/camera_linux.h'
|
||||
include-directives:
|
||||
- 'src/camera_linux.h'
|
||||
preamble: |
|
||||
// ignore_for_file: always_specify_types
|
||||
// ignore_for_file: camel_case_types
|
||||
// ignore_for_file: non_constant_identifier_names
|
||||
comments:
|
||||
style: any
|
||||
length: full
|
|
@ -0,0 +1,38 @@
|
|||
import 'dart:async';
|
||||
import 'dart:ffi';
|
||||
import 'dart:typed_data';
|
||||
import 'camera_linux_bindings_generated.dart';
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
class CameraLinux {
|
||||
late CameraLinuxBindings _bindings;
|
||||
|
||||
CameraLinux() {
|
||||
final dylib = DynamicLibrary.open('libcamera_linux.so');
|
||||
_bindings = CameraLinuxBindings(dylib);
|
||||
}
|
||||
|
||||
// Open Default Camera
|
||||
Future<void> initializeCamera() async {
|
||||
_bindings.startVideoCaptureInThread();
|
||||
}
|
||||
|
||||
// Close The Camera
|
||||
void stopCamera() {
|
||||
_bindings.stopVideoCapture();
|
||||
}
|
||||
|
||||
// Capture The Frame
|
||||
Future<Uint8List> captureImage() async {
|
||||
final lengthPtr = calloc<Int>();
|
||||
Pointer<Uint8> framePointer = _bindings.getLatestFrameBytes(lengthPtr);
|
||||
final latestFrame = getLatestFrameData(framePointer, lengthPtr.value);
|
||||
return latestFrame;
|
||||
}
|
||||
|
||||
// Get The Latest Frame
|
||||
Uint8List getLatestFrameData(Pointer<Uint8> framePointer, frameSize) {
|
||||
List<int> frameList = framePointer.asTypedList(frameSize);
|
||||
return Uint8List.fromList(frameList);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
// ignore_for_file: always_specify_types
|
||||
// ignore_for_file: camel_case_types
|
||||
// ignore_for_file: non_constant_identifier_names
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
//
|
||||
// Generated by `package:ffigen`.
|
||||
import 'dart:ffi' as ffi;
|
||||
|
||||
/// Bindings for `src/camera_linux.h`.
|
||||
///
|
||||
/// Regenerate bindings with `flutter pub run ffigen --config ffigen.yaml`.
|
||||
///
|
||||
class CameraLinuxBindings {
|
||||
/// Holds the symbol lookup function.
|
||||
final ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName) _lookup;
|
||||
|
||||
/// The symbols are looked up in [dynamicLibrary].
|
||||
CameraLinuxBindings(ffi.DynamicLibrary dynamicLibrary) : _lookup = dynamicLibrary.lookup;
|
||||
|
||||
/// The symbols are looked up with [lookup].
|
||||
CameraLinuxBindings.fromLookup(ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName) lookup) : _lookup = lookup;
|
||||
|
||||
void startVideoCaptureInThread() {
|
||||
return _startVideoCaptureInThread();
|
||||
}
|
||||
|
||||
late final _startVideoCaptureInThreadPtr = _lookup<ffi.NativeFunction<ffi.Void Function()>>('startVideoCaptureInThread');
|
||||
late final _startVideoCaptureInThread = _startVideoCaptureInThreadPtr.asFunction<void Function()>();
|
||||
|
||||
void stopVideoCapture() {
|
||||
return _stopVideoCapture();
|
||||
}
|
||||
|
||||
late final _stopVideoCapturePtr = _lookup<ffi.NativeFunction<ffi.Void Function()>>('stopVideoCapture');
|
||||
late final _stopVideoCapture = _stopVideoCapturePtr.asFunction<void Function()>();
|
||||
|
||||
ffi.Pointer<ffi.Uint8> getLatestFrameBytes(
|
||||
ffi.Pointer<ffi.Int> length,
|
||||
) {
|
||||
return _getLatestFrameBytes(
|
||||
length,
|
||||
);
|
||||
}
|
||||
|
||||
late final _getLatestFrameBytesPtr = _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Uint8> Function(ffi.Pointer<ffi.Int>)>>('getLatestFrameBytes');
|
||||
late final _getLatestFrameBytes = _getLatestFrameBytesPtr.asFunction<ffi.Pointer<ffi.Uint8> Function(ffi.Pointer<ffi.Int>)>();
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
# The Flutter tooling requires that developers have CMake 3.10 or later
|
||||
# installed. You should not increase this version, as doing so will cause
|
||||
# the plugin to fail to compile for some customers of the plugin.
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
# Project-level configuration.
|
||||
set(PROJECT_NAME "camera_linux")
|
||||
project(${PROJECT_NAME} LANGUAGES CXX)
|
||||
|
||||
# Invoke the build for native code shared with the other target platforms.
|
||||
# This can be changed to accommodate different builds.
|
||||
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../src" "${CMAKE_CURRENT_BINARY_DIR}/shared")
|
||||
|
||||
# List of absolute paths to libraries that should be bundled with the plugin.
|
||||
# This list could contain prebuilt libraries, or libraries created by an
|
||||
# external build triggered from this build file.
|
||||
set(camera_linux_bundled_libraries
|
||||
# Defined in ../src/CMakeLists.txt.
|
||||
# This can be changed to accommodate different builds.
|
||||
$<TARGET_FILE:camera_linux>
|
||||
PARENT_SCOPE
|
||||
)
|
|
@ -0,0 +1,73 @@
|
|||
name: camera_linux
|
||||
description: Take pictures from camere on linux platform.
|
||||
version: 0.0.8
|
||||
homepage: https://github.com/islamroshan/camera-linux.git
|
||||
|
||||
environment:
|
||||
sdk: '>=3.1.0 <4.0.0'
|
||||
flutter: '>=3.3.0'
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
plugin_platform_interface: ^2.0.2
|
||||
ffi: ^2.0.1
|
||||
|
||||
dev_dependencies:
|
||||
ffigen: 11.0.0
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^2.0.0
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
||||
# The following section is specific to Flutter packages.
|
||||
flutter:
|
||||
# This section identifies this Flutter project as a plugin project.
|
||||
# The 'pluginClass' specifies the class (in Java, Kotlin, Swift, Objective-C, etc.)
|
||||
# which should be registered in the plugin registry. This is required for
|
||||
# using method channels.
|
||||
# The Android 'package' specifies package in which the registered class is.
|
||||
# This is required for using method channels on Android.
|
||||
# The 'ffiPlugin' specifies that native code should be built and bundled.
|
||||
# This is required for using `dart:ffi`.
|
||||
# All these are used by the tooling to maintain consistency when
|
||||
# adding or updating assets for this project.
|
||||
#
|
||||
# Please refer to README.md for a detailed explanation.
|
||||
plugin:
|
||||
platforms:
|
||||
linux:
|
||||
ffiPlugin: true
|
||||
|
||||
# To add assets to your plugin package, add an assets section, like this:
|
||||
# assets:
|
||||
# - images/a_dot_burr.jpeg
|
||||
# - images/a_dot_ham.jpeg
|
||||
#
|
||||
# For details regarding assets in packages, see
|
||||
# https://flutter.dev/assets-and-images/#from-packages
|
||||
#
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
# https://flutter.dev/assets-and-images/#resolution-aware
|
||||
|
||||
# To add custom fonts to your plugin package, add a fonts section here,
|
||||
# in this "flutter" section. Each entry in this list should have a
|
||||
# "family" key with the font family name, and a "fonts" key with a
|
||||
# list giving the asset and other descriptors for the font. For
|
||||
# example:
|
||||
# fonts:
|
||||
# - family: Schyler
|
||||
# fonts:
|
||||
# - asset: fonts/Schyler-Regular.ttf
|
||||
# - asset: fonts/Schyler-Italic.ttf
|
||||
# style: italic
|
||||
# - family: Trajan Pro
|
||||
# fonts:
|
||||
# - asset: fonts/TrajanPro.ttf
|
||||
# - asset: fonts/TrajanPro_Bold.ttf
|
||||
# weight: 700
|
||||
#
|
||||
# For details regarding fonts in packages, see
|
||||
# https://flutter.dev/custom-fonts/#from-packages
|
|
@ -0,0 +1,20 @@
|
|||
cmake_minimum_required(VERSION 3.10)
|
||||
project(camera_linux_library VERSION 0.0.1 LANGUAGES C CXX)
|
||||
|
||||
set(SOURCE_FILES opencv_wrapper.cpp)
|
||||
add_library(opencv_wrapper SHARED ${SOURCE_FILES})
|
||||
|
||||
find_package(OpenCV REQUIRED)
|
||||
include_directories(${OpenCV_INCLUDE_DIRS})
|
||||
|
||||
target_link_libraries(opencv_wrapper ${OpenCV_LIBS})
|
||||
|
||||
add_library(camera_linux SHARED "camera_linux.c")
|
||||
target_link_libraries(camera_linux opencv_wrapper)
|
||||
|
||||
set_target_properties(camera_linux PROPERTIES
|
||||
PUBLIC_HEADER camera_linux.h
|
||||
OUTPUT_NAME "camera_linux"
|
||||
)
|
||||
|
||||
target_compile_definitions(camera_linux PUBLIC DART_SHARED_LIB)
|
|
@ -0,0 +1,5 @@
|
|||
#include "camera_linux.h"
|
||||
|
||||
void startVideoCaptureInThread();
|
||||
void stopVideoCapture();
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void startVideoCaptureInThread();
|
||||
void stopVideoCapture();
|
||||
uint8_t* getLatestFrameBytes(int* length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
#include <iostream>
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
std::thread videoThread;
|
||||
std::atomic<bool> stopFlag(false);
|
||||
Mat latestFrame;
|
||||
|
||||
// Extern C block to expose the function to C
|
||||
extern "C" {
|
||||
// Function to capture video frames
|
||||
void runVideoCapture() {
|
||||
VideoCapture cap;
|
||||
int deviceID = 0; // 0 = open default camera
|
||||
int apiID = cv::CAP_ANY; // 0 = autodetect default API
|
||||
cap.open(deviceID, apiID);
|
||||
cap.set(cv::CAP_PROP_FRAME_WIDTH, 160);
|
||||
cap.set(cv::CAP_PROP_FRAME_HEIGHT, 120);
|
||||
if (!cap.isOpened()) {
|
||||
cerr << "ERROR! Unable to open camera\n";
|
||||
return ;
|
||||
}
|
||||
|
||||
while (!stopFlag.load()) {
|
||||
cap >> latestFrame;
|
||||
if (latestFrame.empty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
cap.release();
|
||||
}
|
||||
|
||||
void startVideoCaptureInThread() {
|
||||
stopFlag = false;
|
||||
videoThread = std::thread(runVideoCapture);
|
||||
videoThread.detach();
|
||||
}
|
||||
|
||||
void stopVideoCapture() {
|
||||
stopFlag = true;
|
||||
if (videoThread.joinable()) {
|
||||
videoThread.join();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t* getLatestFrameBytes(int* length) {
|
||||
// Ensure the pointer is valid
|
||||
if (!length) {
|
||||
return nullptr;
|
||||
}
|
||||
*length = 0; // Initialize length to 0
|
||||
if (latestFrame.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
vector<int> compression_params;
|
||||
compression_params.push_back(IMWRITE_JPEG_QUALITY);
|
||||
compression_params.push_back(50);
|
||||
// Encode the frame as JPEG
|
||||
vector<uint8_t> buf;
|
||||
bool encodeSuccess = imencode(".jpg", latestFrame, buf, compression_params );
|
||||
|
||||
// Check if encoding was successful
|
||||
if (!encodeSuccess || buf.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
*length = static_cast<int>(buf.size());
|
||||
cout << buf.size() << endl;
|
||||
// Allocate memory and copy data
|
||||
uint8_t* data = new uint8_t[(*length)];
|
||||
|
||||
if (!data) {
|
||||
cout << "Memory allocation failed." << endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
memcpy(data, buf.data(), *length);
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,673 +0,0 @@
|
|||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
_fe_analyzer_shared:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: _fe_analyzer_shared
|
||||
sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "67.0.0"
|
||||
analyzer:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: analyzer
|
||||
sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.4.1"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: args
|
||||
sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.2"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.11.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
build:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build
|
||||
sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
build_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_config
|
||||
sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
build_daemon:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_daemon
|
||||
sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.1"
|
||||
build_resolvers:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_resolvers
|
||||
sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.2"
|
||||
build_runner:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: build_runner
|
||||
sha256: "581bacf68f89ec8792f5e5a0b2c4decd1c948e97ce659dc783688c8a88fbec21"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.8"
|
||||
build_runner_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_runner_core
|
||||
sha256: "4ae8ffe5ac758da294ecf1802f2aff01558d8b1b00616aa7538ea9a8a5d50799"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.3.0"
|
||||
built_collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: built_collection
|
||||
sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.1.1"
|
||||
built_value:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: built_value
|
||||
sha256: fedde275e0a6b798c3296963c5cd224e3e1b55d0e478d5b7e65e6b540f363a0e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.9.1"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: characters
|
||||
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
checked_yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: checked_yaml
|
||||
sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
code_builder:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: code_builder
|
||||
sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.10.0"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.18.0"
|
||||
connectivity_plus_platform_interface:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "../connectivity_plus_platform_interface"
|
||||
relative: true
|
||||
source: path
|
||||
version: "1.2.4"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: convert
|
||||
sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.1"
|
||||
coverage:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: coverage
|
||||
sha256: "8acabb8306b57a409bf4c83522065672ee13179297a6bb0cb9ead73948df7c76"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.7.2"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.3"
|
||||
dart_style:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: dart_style
|
||||
sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.6"
|
||||
dbus:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: dbus
|
||||
sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.10"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.0"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fixnum
|
||||
sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_lints
|
||||
sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_web_plugins:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
frontend_server_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: frontend_server_client
|
||||
sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.0"
|
||||
glob:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: glob
|
||||
sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
graphs:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: graphs
|
||||
sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.1"
|
||||
http_multi_server:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_multi_server
|
||||
sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.1"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_parser
|
||||
sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.2"
|
||||
io:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: io
|
||||
sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
js:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: js
|
||||
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.7"
|
||||
json_annotation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: json_annotation
|
||||
sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.8.1"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker
|
||||
sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "10.0.0"
|
||||
leak_tracker_flutter_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_flutter_testing
|
||||
sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
leak_tracker_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_testing
|
||||
sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: lints
|
||||
sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
logging:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: logging
|
||||
sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.16+1"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.8.0"
|
||||
meta:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: meta
|
||||
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: mime
|
||||
sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.5"
|
||||
mockito:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: mockito
|
||||
sha256: "6841eed20a7befac0ce07df8116c8b8233ed1f4486a7647c7fc5a02ae6163917"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.4.4"
|
||||
node_preamble:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: node_preamble
|
||||
sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
package_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_config
|
||||
sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path
|
||||
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.0"
|
||||
petitparser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: petitparser
|
||||
sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.2"
|
||||
plugin_platform_interface:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: plugin_platform_interface
|
||||
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.8"
|
||||
pool:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pool
|
||||
sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.5.1"
|
||||
pub_semver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pub_semver
|
||||
sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
pubspec_parse:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pubspec_parse
|
||||
sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.3"
|
||||
shelf:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf
|
||||
sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.1"
|
||||
shelf_packages_handler:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_packages_handler
|
||||
sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.2"
|
||||
shelf_static:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_static
|
||||
sha256: a41d3f53c4adf0f57480578c1d61d90342cd617de7fc8077b1304643c2d85c1e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
shelf_web_socket:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_web_socket
|
||||
sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.99"
|
||||
source_gen:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_gen
|
||||
sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.5.0"
|
||||
source_map_stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_map_stack_trace
|
||||
sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
source_maps:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_maps
|
||||
sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.10.12"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.1"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
stream_transform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_transform
|
||||
sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
test:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: test
|
||||
sha256: a1f7595805820fcc05e5c52e3a231aedd0b72972cb333e8c738a8b1239448b6f
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.24.9"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.1"
|
||||
test_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_core
|
||||
sha256: a757b14fc47507060a162cc2530d9a4a2f92f5100a952c7443b5cad5ef5b106a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.9"
|
||||
timing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: timing
|
||||
sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.2"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_math
|
||||
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
vm_service:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "13.0.0"
|
||||
watcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: watcher
|
||||
sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.1"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket_channel
|
||||
sha256: "1d8e795e2a8b3730c41b8a98a2dff2e0fb57ae6f0764a1c46ec5915387d257b2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.4"
|
||||
webkit_inspection_protocol:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webkit_inspection_protocol
|
||||
sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
xml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xml
|
||||
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.5.0"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: yaml
|
||||
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
sdks:
|
||||
dart: ">=3.3.0 <4.0.0"
|
||||
flutter: ">=3.7.0"
|
|
@ -34,7 +34,6 @@ dependencies:
|
|||
js: ^0.6.3
|
||||
meta: ^1.8.0
|
||||
|
||||
cwtch: any
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
|
|
@ -24,8 +24,11 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
|
||||
import 'linkify.dart';
|
||||
|
||||
|
@ -126,7 +129,7 @@ class SelectableLinkify extends StatelessWidget {
|
|||
/// Called when the user changes the selection of text (including the cursor location).
|
||||
final SelectionChangedCallback? onSelectionChanged;
|
||||
|
||||
final BoxConstraints? constraints;
|
||||
final BoxConstraints constraints;
|
||||
|
||||
const SelectableLinkify({
|
||||
Key? key,
|
||||
|
@ -161,7 +164,7 @@ class SelectableLinkify extends StatelessWidget {
|
|||
this.cursorHeight,
|
||||
this.selectionControls,
|
||||
this.onSelectionChanged,
|
||||
this.constraints,
|
||||
required this.constraints,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
|
@ -235,7 +238,7 @@ TextSpan buildTextSpan(
|
|||
LinkCallback? onOpen,
|
||||
required BuildContext context,
|
||||
bool useMouseRegion = false,
|
||||
BoxConstraints? constraints,
|
||||
required BoxConstraints constraints,
|
||||
}) {
|
||||
// Ok, so the problem here is that Flutter really wants to optimize this function
|
||||
// out of the rebuild process. This is fine when the screen gets smaller because
|
||||
|
@ -247,7 +250,7 @@ TextSpan buildTextSpan(
|
|||
// (I tried a few other things, including the docs-sanctioned MediaQuery.sizeOf(context) - which promises a rebuild
|
||||
// but Flutter is pretty good at optimizing "useless" checks out)
|
||||
String inlineText = "\u0020";
|
||||
if (constraints != null && constraints.maxWidth % 2 == 0) {
|
||||
if (constraints.maxWidth % 2 == 0) {
|
||||
inlineText = "\u00A0";
|
||||
}
|
||||
elements.add(TextElement(inlineText));
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
# Run with `flutter pub run ffigen --config ffigen.yaml`.
|
||||
name: MiniAudioBindings
|
||||
description: |
|
||||
Bindings for `src/audio.h`.
|
||||
|
||||
Regenerate bindings with `flutter pub run ffigen --config ffigen.yaml`.
|
||||
output: 'lib/miniaudio_bindings_generated.dart'
|
||||
headers:
|
||||
entry-points:
|
||||
- 'src/audio.h'
|
||||
include-directives:
|
||||
- 'src/audio.h'
|
||||
preamble: |
|
||||
// ignore_for_file: always_specify_types
|
||||
// ignore_for_file: camel_case_types
|
||||
// ignore_for_file: non_constant_identifier_names
|
||||
comments:
|
||||
style: any
|
||||
length: full
|
|
@ -0,0 +1,27 @@
|
|||
import 'dart:async';
|
||||
import 'dart:ffi';
|
||||
import 'dart:typed_data';
|
||||
import 'package:miniaudio/miniaudio_bindings_generated.dart';
|
||||
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
class MiniAudio {
|
||||
late MiniAudioBindings _bindings;
|
||||
|
||||
MiniAudio() {
|
||||
final dylib = DynamicLibrary.open('libminiaudio.so');
|
||||
_bindings = MiniAudioBindings(dylib);
|
||||
}
|
||||
|
||||
Future<void> initAudio() async {
|
||||
_bindings.initAudio();
|
||||
}
|
||||
|
||||
// Open Default Camera
|
||||
Future<void> playAudio(String file) async {
|
||||
var filePtr = file.toNativeUtf8();
|
||||
_bindings.playAudio(filePtr.cast());
|
||||
malloc.free(filePtr);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
// ignore_for_file: always_specify_types
|
||||
// ignore_for_file: camel_case_types
|
||||
// ignore_for_file: non_constant_identifier_names
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
//
|
||||
// Generated by `package:ffigen`.
|
||||
import 'dart:ffi' as ffi;
|
||||
|
||||
/// Bindings for `src/audio.h`.
|
||||
///
|
||||
/// Regenerate bindings with `flutter pub run ffigen --config ffigen.yaml`.
|
||||
///
|
||||
class MiniAudioBindings {
|
||||
/// Holds the symbol lookup function.
|
||||
final ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
|
||||
_lookup;
|
||||
|
||||
/// The symbols are looked up in [dynamicLibrary].
|
||||
MiniAudioBindings(ffi.DynamicLibrary dynamicLibrary)
|
||||
: _lookup = dynamicLibrary.lookup;
|
||||
|
||||
/// The symbols are looked up with [lookup].
|
||||
MiniAudioBindings.fromLookup(
|
||||
ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
|
||||
lookup)
|
||||
: _lookup = lookup;
|
||||
|
||||
void initAudio() {
|
||||
return _initAudio();
|
||||
}
|
||||
|
||||
late final _initAudioPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function()>>('initAudio');
|
||||
late final _initAudio = _initAudioPtr.asFunction<void Function()>();
|
||||
|
||||
void playAudio(
|
||||
ffi.Pointer<ffi.Char> file,
|
||||
) {
|
||||
return _playAudio(
|
||||
file,
|
||||
);
|
||||
}
|
||||
|
||||
late final _playAudioPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Char>)>>(
|
||||
'playAudio');
|
||||
late final _playAudio =
|
||||
_playAudioPtr.asFunction<void Function(ffi.Pointer<ffi.Char>)>();
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
# The Flutter tooling requires that developers have CMake 3.10 or later
|
||||
# installed. You should not increase this version, as doing so will cause
|
||||
# the plugin to fail to compile for some customers of the plugin.
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
# Project-level configuration.
|
||||
set(PROJECT_NAME "miniaudio")
|
||||
project(${PROJECT_NAME} LANGUAGES CXX)
|
||||
|
||||
# Invoke the build for native code shared with the other target platforms.
|
||||
# This can be changed to accommodate different builds.
|
||||
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../src" "${CMAKE_CURRENT_BINARY_DIR}/shared")
|
||||
|
||||
# List of absolute paths to libraries that should be bundled with the plugin.
|
||||
# This list could contain prebuilt libraries, or libraries created by an
|
||||
# external build triggered from this build file.
|
||||
set(miniaudio_bundled_libraries
|
||||
# Defined in ../src/CMakeLists.txt.
|
||||
# This can be changed to accommodate different builds.
|
||||
$<TARGET_FILE:miniaudio>
|
||||
PARENT_SCOPE
|
||||
)
|
|
@ -0,0 +1,333 @@
|
|||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
archive:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: archive
|
||||
sha256: "22600aa1e926be775fa5fe7e6894e7fb3df9efda8891c73f70fb3262399a432d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.4.10"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: args
|
||||
sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.2"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.11.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: characters
|
||||
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
cli_util:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cli_util
|
||||
sha256: "66f86e916d285c1a93d3b79587d94bd71984a66aac4ff74e524cfa7877f1395c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.5"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.18.0"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: convert
|
||||
sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.1"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.3"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
ffi:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: ffi
|
||||
sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
ffigen:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: ffigen
|
||||
sha256: ec6a2439159d27c871d92862fb9f3012ef19d9ec4b0fa383c69c8553b2dd2ac5
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.2"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.4"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_lints
|
||||
sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
glob:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: glob
|
||||
sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
image:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: image
|
||||
sha256: "8e9d133755c3e84c73288363e6343157c383a0c6c56fc51afcc5d4d7180306d6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.3.0"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
sha256: "4186c61b32f99e60f011f7160e32c89a758ae9b1d0c6d28e2c02ef0382300e2b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.0"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: lints
|
||||
sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
logging:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: logging
|
||||
sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.16"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.0"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path
|
||||
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.8.3"
|
||||
petitparser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: petitparser
|
||||
sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.2"
|
||||
plugin_platform_interface:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: plugin_platform_interface
|
||||
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.8"
|
||||
pointycastle:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pointycastle
|
||||
sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.7.4"
|
||||
quiver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: quiver
|
||||
sha256: b1c1ac5ce6688d77f65f3375a9abb9319b3cb32486bdc7a1e0fdf004d7ba4e47
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.1"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.99"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.1"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.1"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.2"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_math
|
||||
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.0"
|
||||
xml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xml
|
||||
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.5.0"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: yaml
|
||||
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
sdks:
|
||||
dart: ">=3.2.0 <4.0.0"
|
||||
flutter: ">=3.3.0"
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue