Compare commits

..

52 commits

Author SHA1 Message Date
c0be7552d5 Gramatical error 2024-10-17 21:25:58 -04:00
0a6473aa83 Update README.md 2024-10-17 21:25:23 -04:00
c02c314725 Update README.md 2024-10-17 21:25:04 -04:00
695a85b20d Update README.md 2024-10-17 21:23:53 -04:00
558a2e0507 Updated due to issue 2024-10-17 20:57:24 -04:00
7bd329ebef Merge pull request 'Release 0.0.3 Main Merge' (#3) from dev into main
Reviewed-on: #3
We need to work on woodpecker
2024-10-17 18:43:25 -04:00
74a6f811e0 Release
Some checks failed
ci/woodpecker/push/workflow Pipeline failed
2024-10-17 18:39:13 -04:00
3dda4297d4 Changed a string
Some checks failed
ci/woodpecker/push/workflow Pipeline failed
2024-10-17 18:22:52 -04:00
1e2731bd5a Icons 2024-10-17 18:14:03 -04:00
9d42581bbf Changed image in readme
Some checks failed
ci/woodpecker/push/workflow Pipeline failed
2024-10-17 17:53:54 -04:00
c3f205ae42 New logo
Some checks failed
ci/woodpecker/push/workflow Pipeline failed
2024-10-17 17:49:33 -04:00
6c27121258 AAA
Some checks failed
ci/woodpecker/push/workflow Pipeline failed
2024-10-14 18:42:18 -04:00
24672ec104 Test 4 2024-10-14 18:41:56 -04:00
6b88d5b409 Test 3 2024-10-14 18:40:52 -04:00
32d06ed3d7 Test 2
All checks were successful
ci/woodpecker/push/workflow Pipeline was successful
2024-10-14 18:39:00 -04:00
731ff7c915 test
Some checks failed
ci/woodpecker/push/workflow Pipeline failed
2024-10-14 18:28:05 -04:00
e5b847002f test
Some checks failed
ci/woodpecker/push/workflow Pipeline failed
2024-10-14 18:27:12 -04:00
cf3c45f222 Again
Some checks failed
ci/woodpecker/push/workflow Pipeline failed
2024-10-14 18:21:31 -04:00
8653092804 Test again
Some checks failed
ci/woodpecker/push/workflow Pipeline failed
2024-10-14 18:20:19 -04:00
dd4a189409 Test
Some checks failed
ci/woodpecker/push/workflow Pipeline failed
2024-10-14 18:18:19 -04:00
ee9bc2aec0 Fixed issue
Some checks failed
ci/woodpecker/push/workflow Pipeline failed
2024-10-14 18:11:37 -04:00
fbdad99200 1st Pipeline test 2024-10-14 18:00:33 -04:00
9fac523327 testing woodpecker 2024-10-14 15:48:43 -04:00
72742d3fe3 Changed it back 2024-10-13 23:57:11 -04:00
0032153056 Changed to testing 2024-10-13 23:54:28 -04:00
69659c5336 Testing 2024-10-11 15:19:07 -04:00
a691f04de6 Chnaged some compile stuff 2024-10-11 15:17:13 -04:00
3c04c7a7f3 Added Icons and removed some details 2024-10-11 14:50:25 -04:00
60e8e428e8 Added an app bar for images 2024-10-11 11:10:34 -04:00
38a277348f Test 2024-10-11 10:12:34 -04:00
8b6f5bc00c Fixed several issues 2024-07-30 14:54:38 -04:00
de0021b144 Merge branch 'dev' of https://git.mrdab.vore.media/ThatOneJackalGuy/OpenContacts into dev 2024-07-25 17:02:59 -04:00
b1fbc4b46d Made some changes 2024-07-25 17:02:29 -04:00
29a50bb0e7 Merge pull request 'Merge Request 1' (#1) from dev into main
Reviewed-on: #1 on July 15th, 2024 @ 11:52AM Atlantic Standard Time
2024-07-15 11:52:46 -04:00
f8cd5c27cd Merge branch 'main' into dev 2024-07-15 11:51:25 -04:00
ae5c2bab1d Finishing 2024-07-15 11:45:55 -04:00
58dd75a5db Changed README 2024-07-15 11:30:40 -04:00
198f99d8f7 test 2024-07-15 11:30:08 -04:00
1511a4b253 Changing some things before release 2024-07-15 11:28:30 -04:00
99c6cfd572 Added a comment 2024-07-15 11:18:48 -04:00
66c8c06673 Preping for merge in main 2024-07-15 11:13:40 -04:00
3953f80940 Changed several strings 2024-07-15 02:08:17 -04:00
bfcee03185 Changed README 2024-07-15 01:00:34 -04:00
5834dedf16 Update README.md 2024-07-15 00:59:22 -04:00
a844815424 It works! 2024-07-15 00:23:04 -04:00
c74501eb34 Got sociable status working 2024-07-15 00:09:15 -04:00
fd6bfd2ea4 My bad, willco later 2024-07-14 21:59:06 -04:00
bb7c15d406 Just email reset 2024-07-14 21:56:16 -04:00
Garrett Watson
3051127a0f
Update iOS build config + fix appicons manifest (#29)
* chore(ios): update build config

* fix(ios): fix appicons manifest
2024-03-17 23:00:06 +01:00
Nutcake
02f3514ad3
Bump version number 2024-01-27 16:16:34 +01:00
Nutcake
cc92786af2
Isovel/rtf color parsing (#27)
* feat: improve RTF color parsing to be more consistent with Resonite

* chore: optimize some regex used in RTF tag parsing

---------

Co-authored-by: Garrett Watson <toast@isota.ch>
2024-01-27 16:15:27 +01:00
Nutcake
76e32887e4
Isovel/contacts sorting (#26)
* feat: update contacts list sorting + correctly handle headless hosts
---------

Co-authored-by: Garrett Watson <toast@isota.ch>
2024-01-27 15:55:55 +01:00
145 changed files with 1337 additions and 1163 deletions

2
.gitignore vendored
View file

@ -43,3 +43,5 @@ app.*.map.json
/android/app/profile
/android/app/release
/android/key.properties
# NEVER STORE ANY KEY OR API KEYS WHEN COMMITING CODE!!

15
.woodpecker/workflow.yaml Normal file
View file

@ -0,0 +1,15 @@
when:
- event: push
branch: dev
steps:
- name: build
image: instrumentisto/flutter
commands:
- cd OpenContacts
- echo "Starting to build..."
- flutter build --debug
- name: Deploy
image: debian
commands:
- echo "Hello World"

View file

@ -1,10 +1,15 @@
<img src="https://github.com/Nutcake/ReCon/raw/main/assets/images/logo512.png" width="200"/>
<img src="https://raw.githubusercontent.com/Mrdabup/OpenContacts/refs/heads/dev/assets/images/logo512.png" width="200"/>
# ReCon
# OpenContacts
A Resonite Contacts App
A Resonite Contacts App, based on Nutcake's Recon.
[Get the latest version of OpenContacts here](https://git.mrdab.vore.media/ThatOneJackalGuy/OpenContacts/releases)
[Available on github too!](https://github.com/Mrdabup/OpenContacts/releases)
[Get ReCon here](https://github.com/Nutcake/ReCon)
[Get it here](https://github.com/Nutcake/ReCon/releases/latest)
## Building
@ -15,6 +20,7 @@ Currently only Android is fully supported.
The app works on other platforms, though not every feature will be functional.
For example, notifications are currently not supported on non-android builds.
## Screenshots
### Screenshots
TODO: Screenshots!
<img src="https://github.com/Nutcake/ReCon/assets/10452593/a46ccf8a-0a9f-4518-98e6-84fad2d7bf26" width=198/> <img src="https://github.com/Nutcake/ReCon/assets/10452593/5d158f58-cd27-4a68-abf3-9068e92b6a82" width=198/> <img src="https://github.com/Nutcake/ReCon/assets/10452593/f2ce95ef-e513-46cb-9654-31e74cdc7c09" width=198/> <img src="https://github.com/Nutcake/ReCon/assets/10452593/58ef5e5e-1b53-4a47-92f8-bcbcba7a1e86" width=198/>
<!--<img src="https://github.com/Nutcake/ReCon/assets/10452593/a46ccf8a-0a9f-4518-98e6-84fad2d7bf26" width=198/> <img src="https://github.com/Nutcake/ReCon/assets/10452593/5d158f58-cd27-4a68-abf3-9068e92b6a82" width=198/> <img src="https://github.com/Nutcake/ReCon/assets/10452593/f2ce95ef-e513-46cb-9654-31e74cdc7c09" width=198/> <img src="https://github.com/Nutcake/ReCon/assets/10452593/58ef5e5e-1b53-4a47-92f8-bcbcba7a1e86" width=198/>-->

View file

@ -49,7 +49,7 @@ android {
}
defaultConfig {
applicationId "me.voidspace.recon"
applicationId "de.tojcklguy.opencontacts"
minSdkVersion 24
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()

View file

@ -1,5 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="de.voidspace.recon">
package="de.tojcklguy.opencontacts">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.

View file

@ -1,5 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="de.voidspace.recon">
package="de.tojcklguy.opencontacts">
<!-- Required to fetch data from the internet. -->
<uses-permission android:name="android.permission.INTERNET" />
@ -7,9 +7,9 @@
<!-- Optional, you'll have to check this permission by yourself. -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:label="ReCon"
android:label="OpenContacts"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
android:icon="@mipmap/launcher_icon">
<activity
android:name=".MainActivity"
android:exported="true"

View file

@ -1,6 +1,6 @@
package de.voidspace.recon
package de.tojcklguy.opencontacts
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity() {
}
}

View file

@ -3,4 +3,4 @@ package me.voidspace.recon
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity() {
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -1,5 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="de.voidspace.recon">
package="de.tojcklguy.opencontacts">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

View file

@ -51,9 +51,9 @@ PODS:
- Flutter
- flutter_secure_storage (6.0.0):
- Flutter
- FMDB (2.7.5):
- FMDB/standard (= 2.7.5)
- FMDB/standard (2.7.5)
- FMDB (2.7.9):
- FMDB/standard (= 2.7.9)
- FMDB/standard (2.7.9)
- image_picker_ios (0.0.1):
- Flutter
- just_audio (0.0.1):
@ -68,9 +68,9 @@ PODS:
- record_darwin (1.0.0):
- Flutter
- FlutterMacOS
- SDWebImage (5.13.2):
- SDWebImage/Core (= 5.13.2)
- SDWebImage/Core (5.13.2)
- SDWebImage (5.19.0):
- SDWebImage/Core (= 5.19.0)
- SDWebImage/Core (5.19.0)
- share_plus (0.0.1):
- Flutter
- sqflite (0.0.3):
@ -161,14 +161,14 @@ SPEC CHECKSUMS:
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
FMDB: aa44149f6fb634b1ac54f64f47064bb0d0c5a032
image_picker_ios: 4a8aadfbb6dc30ad5141a2ce3832af9214a705b5
just_audio: baa7252489dbcf47a4c7cc9ca663e9661c99aafa
package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6
record_darwin: 1f6619f2abac4d1ca91d3eeab038c980d76f1517
SDWebImage: 72f86271a6f3139cc7e4a89220946489d4b9a866
SDWebImage: 981fd7e860af070920f249fd092420006014c3eb
share_plus: c3fef564749587fc939ef86ffb283ceac0baf9f5
sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a
SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f
@ -177,4 +177,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: 0a7d5b7d0e53420cb0284f7b2f171f93843b94d2
COCOAPODS: 1.12.1
COCOAPODS: 1.14.3

View file

@ -7,15 +7,15 @@
objects = {
/* Begin PBXBuildFile section */
0C919EFF59BB245CE33C1729 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AD8D55317A9F9C1E8BDC309E /* Pods_RunnerTests.framework */; };
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
3EACF4502AF94B2E0009EB00 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C3BAB80CE2FD566CD74754C6 /* Pods_Runner.framework */; };
3EE80C682BA655DB0086A0C6 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D3DE141E94870D9CA578104 /* Pods_Runner.framework */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
A04538A4FD002863EA8D7E2E /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B83C597EDF1CEFE95FFFB1B /* Pods_RunnerTests.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -31,29 +31,29 @@
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
2A38106953F973A4A4D2889C /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
35345364120A3EBED9C200D8 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
3D3DE141E94870D9CA578104 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3EACF44C2AF946870009EB00 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
3EACF44D2AF94B1B0009EB00 /* sqflite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = sqflite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
6357E70700B420135CF38106 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
4013FCB2867BE8C285FCE973 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
73E6CA98A4DD47389AC0DD2C /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
8B83C597EDF1CEFE95FFFB1B /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
947052A3147FEB296CDB1CF8 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* ReCon.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ReCon.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146EE1CF9000F007C117D /* recon.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = recon.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
98689629DBCBD9B9079D4BCB /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
9B70C4D26DEBAB78C4541963 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
ACF34F80AF1EDFE1E02822A3 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
C3BAB80CE2FD566CD74754C6 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
AD8D55317A9F9C1E8BDC309E /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
CA3447F4857A0510F7FFE6B7 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
D99312EB7B07F458E04BFDD3 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
DB366C7024A03BCB71242FB5 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -61,7 +61,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
A04538A4FD002863EA8D7E2E /* Pods_RunnerTests.framework in Frameworks */,
0C919EFF59BB245CE33C1729 /* Pods_RunnerTests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -69,7 +69,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
3EACF4502AF94B2E0009EB00 /* Pods_Runner.framework in Frameworks */,
3EE80C682BA655DB0086A0C6 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -110,7 +110,7 @@
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* ReCon.app */,
97C146EE1CF9000F007C117D /* recon.app */,
331C8081294A63A400263BE5 /* RunnerTests.xctest */,
);
name = Products;
@ -135,12 +135,12 @@
EB365C9671FE77D43024480F /* Pods */ = {
isa = PBXGroup;
children = (
98689629DBCBD9B9079D4BCB /* Pods-Runner.debug.xcconfig */,
ACF34F80AF1EDFE1E02822A3 /* Pods-Runner.release.xcconfig */,
9B70C4D26DEBAB78C4541963 /* Pods-Runner.profile.xcconfig */,
35345364120A3EBED9C200D8 /* Pods-RunnerTests.debug.xcconfig */,
6357E70700B420135CF38106 /* Pods-RunnerTests.release.xcconfig */,
947052A3147FEB296CDB1CF8 /* Pods-RunnerTests.profile.xcconfig */,
D99312EB7B07F458E04BFDD3 /* Pods-Runner.debug.xcconfig */,
4013FCB2867BE8C285FCE973 /* Pods-Runner.release.xcconfig */,
CA3447F4857A0510F7FFE6B7 /* Pods-Runner.profile.xcconfig */,
2A38106953F973A4A4D2889C /* Pods-RunnerTests.debug.xcconfig */,
73E6CA98A4DD47389AC0DD2C /* Pods-RunnerTests.release.xcconfig */,
DB366C7024A03BCB71242FB5 /* Pods-RunnerTests.profile.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
@ -149,8 +149,8 @@
isa = PBXGroup;
children = (
3EACF44D2AF94B1B0009EB00 /* sqflite.framework */,
C3BAB80CE2FD566CD74754C6 /* Pods_Runner.framework */,
8B83C597EDF1CEFE95FFFB1B /* Pods_RunnerTests.framework */,
3D3DE141E94870D9CA578104 /* Pods_Runner.framework */,
AD8D55317A9F9C1E8BDC309E /* Pods_RunnerTests.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@ -162,7 +162,7 @@
isa = PBXNativeTarget;
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = (
19ED0D0FE3A6C2191496F46B /* [CP] Check Pods Manifest.lock */,
690A3B0A6C07C9F2F97916FF /* [CP] Check Pods Manifest.lock */,
331C807D294A63A400263BE5 /* Sources */,
331C807F294A63A400263BE5 /* Resources */,
2597599605DD2CD4DB799735 /* Frameworks */,
@ -181,13 +181,13 @@
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
197307D9FE00A90F03801302 /* [CP] Check Pods Manifest.lock */,
8BF7047545265288073F8A43 /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
BDF85620D00D0FE7A8BAEF7B /* [CP] Embed Pods Frameworks */,
3E67E7F8ECF942FF5AF50545 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@ -195,7 +195,7 @@
);
name = Runner;
productName = Runner;
productReference = 97C146EE1CF9000F007C117D /* ReCon.app */;
productReference = 97C146EE1CF9000F007C117D /* recon.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
@ -205,7 +205,7 @@
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
LastUpgradeCheck = 1430;
LastUpgradeCheck = 1530;
ORGANIZATIONNAME = "";
TargetAttributes = {
331C8080294A63A400263BE5 = {
@ -259,29 +259,40 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
197307D9FE00A90F03801302 /* [CP] Check Pods Manifest.lock */ = {
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
3E67E7F8ECF942FF5AF50545 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
19ED0D0FE3A6C2191496F46B /* [CP] Check Pods Manifest.lock */ = {
690A3B0A6C07C9F2F97916FF /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@ -303,21 +314,27 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
8BF7047545265288073F8A43 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
name = "Thin Binary";
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
@ -334,23 +351,6 @@
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
BDF85620D00D0FE7A8BAEF7B /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@ -405,6 +405,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
APPLY_RULES_IN_COPY_HEADERS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
@ -424,6 +425,7 @@
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
@ -435,6 +437,7 @@
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
@ -443,8 +446,13 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
INFOPLIST_KEY_CFBundleDisplayName = ReCon;
INFOPLIST_KEY_CFBundleDisplayName = recon;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
INFOPLIST_KEY_NSDownloadsFolderUsageDescription = "Downloading assets from your inventory";
INFOPLIST_KEY_NSMicrophoneUsageDescription = "Recording voice messages";
INFOPLIST_KEY_UIStatusBarStyle = UIStatusBarStyleDefault;
INFOPLIST_KEY_UISupportedInterfaceOrientations = "";
INFOPLIST_KEY_UIUserInterfaceStyle = Automatic;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
@ -464,9 +472,9 @@
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = P9AV4LPNLL;
ENABLE_BITCODE = NO;
FLUTTER_BUILD_NAME = 0.10.3;
FLUTTER_BUILD_NAME = 0.11.2;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = ReCon;
INFOPLIST_KEY_CFBundleDisplayName = recon;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
@ -474,9 +482,9 @@
"@executable_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = 0.10.3;
PRODUCT_BUNDLE_IDENTIFIER = me.voidspace.recon;
PRODUCT_NAME = ReCon;
MARKETING_VERSION = 0.11.2;
PRODUCT_BUNDLE_IDENTIFIER = ch.isota.recon;
PRODUCT_NAME = recon;
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
@ -485,7 +493,7 @@
};
331C8088294A63A400263BE5 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 35345364120A3EBED9C200D8 /* Pods-RunnerTests.debug.xcconfig */;
baseConfigurationReference = 2A38106953F973A4A4D2889C /* Pods-RunnerTests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
@ -503,7 +511,7 @@
};
331C8089294A63A400263BE5 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 6357E70700B420135CF38106 /* Pods-RunnerTests.release.xcconfig */;
baseConfigurationReference = 73E6CA98A4DD47389AC0DD2C /* Pods-RunnerTests.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
@ -519,7 +527,7 @@
};
331C808A294A63A400263BE5 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 947052A3147FEB296CDB1CF8 /* Pods-RunnerTests.profile.xcconfig */;
baseConfigurationReference = DB366C7024A03BCB71242FB5 /* Pods-RunnerTests.profile.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
@ -537,6 +545,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
APPLY_RULES_IN_COPY_HEADERS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
@ -556,6 +565,7 @@
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
@ -567,6 +577,7 @@
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
@ -581,8 +592,13 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
INFOPLIST_KEY_CFBundleDisplayName = ReCon;
INFOPLIST_KEY_CFBundleDisplayName = recon;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
INFOPLIST_KEY_NSDownloadsFolderUsageDescription = "Downloading assets from your inventory";
INFOPLIST_KEY_NSMicrophoneUsageDescription = "Recording voice messages";
INFOPLIST_KEY_UIStatusBarStyle = UIStatusBarStyleDefault;
INFOPLIST_KEY_UISupportedInterfaceOrientations = "";
INFOPLIST_KEY_UIUserInterfaceStyle = Automatic;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
@ -595,6 +611,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
APPLY_RULES_IN_COPY_HEADERS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
@ -614,6 +631,7 @@
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
@ -625,6 +643,7 @@
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
@ -633,8 +652,13 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
INFOPLIST_KEY_CFBundleDisplayName = ReCon;
INFOPLIST_KEY_CFBundleDisplayName = recon;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
INFOPLIST_KEY_NSDownloadsFolderUsageDescription = "Downloading assets from your inventory";
INFOPLIST_KEY_NSMicrophoneUsageDescription = "Recording voice messages";
INFOPLIST_KEY_UIStatusBarStyle = UIStatusBarStyleDefault;
INFOPLIST_KEY_UISupportedInterfaceOrientations = "";
INFOPLIST_KEY_UIUserInterfaceStyle = Automatic;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
@ -656,9 +680,9 @@
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = P9AV4LPNLL;
ENABLE_BITCODE = NO;
FLUTTER_BUILD_NAME = 0.10.3;
FLUTTER_BUILD_NAME = 0.11.2;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = ReCon;
INFOPLIST_KEY_CFBundleDisplayName = recon;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
@ -666,9 +690,9 @@
"@executable_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = 0.10.3;
PRODUCT_BUNDLE_IDENTIFIER = me.voidspace.recon;
PRODUCT_NAME = ReCon;
MARKETING_VERSION = 0.11.2;
PRODUCT_BUNDLE_IDENTIFIER = ch.isota.recon;
PRODUCT_NAME = recon;
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
@ -686,9 +710,9 @@
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = P9AV4LPNLL;
ENABLE_BITCODE = NO;
FLUTTER_BUILD_NAME = 0.10.3;
FLUTTER_BUILD_NAME = 0.11.2;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = ReCon;
INFOPLIST_KEY_CFBundleDisplayName = recon;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
@ -696,9 +720,9 @@
"@executable_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = 0.10.3;
PRODUCT_BUNDLE_IDENTIFIER = me.voidspace.recon;
PRODUCT_NAME = ReCon;
MARKETING_VERSION = 0.11.2;
PRODUCT_BUNDLE_IDENTIFIER = ch.isota.recon;
PRODUCT_NAME = recon;
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
@ -741,4 +765,4 @@
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}
}

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
LastUpgradeVersion = "1530"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@ -15,7 +15,7 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "ReCon.app"
BuildableName = "recon.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
@ -31,7 +31,7 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "ReCon.app"
BuildableName = "recon.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
@ -65,7 +65,7 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "ReCon.app"
BuildableName = "recon.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
@ -82,7 +82,7 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "ReCon.app"
BuildableName = "recon.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
@ -93,7 +93,7 @@
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
customArchiveName = "ReCon"
customArchiveName = "recon"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View file

@ -1,104 +1,134 @@
{
"images": [
"images" : [
{
"filename": "Icon_40x40@2x.png",
"idiom": "universal",
"scale": "2x",
"size": "40x40"
"filename" : "icon_40x40@2x.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "20x20"
},
{
"filename": "Icon_58x58@2x.png",
"idiom": "universal",
"scale": "2x",
"size": "58x58"
"filename" : "icon_60x60@3x.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "20x20"
},
{
"filename": "Icon_60x60@3x.png",
"idiom": "universal",
"scale": "3x",
"size": "60x60"
"filename" : "icon_58x58@2x.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "29x29"
},
{
"filename": "Icon_76x76@2x.png",
"idiom": "universal",
"scale": "2x",
"size": "76x76"
"filename" : "icon_87x87@3x.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "29x29"
},
{
"filename": "Icon_80x80@2x.png",
"idiom": "universal",
"scale": "2x",
"size": "80x80"
"filename" : "icon_80x80@2x.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "40x40"
},
{
"filename": "Icon_87x87@3x.png",
"idiom": "universal",
"scale": "3x",
"size": "87x87"
"filename" : "icon_120x120@3x.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "40x40"
},
{
"filename": "Icon_114x114@3x.png",
"idiom": "universal",
"scale": "3x",
"size": "114x114"
"filename" : "icon_60x60@2x.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "60x60"
},
{
"filename": "Icon_120x120@2x.png",
"idiom": "universal",
"scale": "2x",
"size": "120x120"
"filename" : "icon_180x180@3x.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "60x60"
},
{
"filename": "Icon_120x120@3x.png",
"idiom": "universal",
"scale": "3x",
"size": "120x120"
"filename" : "icon_40x40@2x 1.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "20x20"
},
{
"filename": "Icon_128x128@2x.png",
"idiom": "universal",
"scale": "2x",
"size": "128x128"
"filename" : "icon_58x58@2x 1.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "29x29"
},
{
"filename": "Icon_136x136@2x.png",
"idiom": "universal",
"scale": "2x",
"size": "136x136"
"filename" : "icon_80x80@2x 1.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "40x40"
},
{
"filename": "Icon_152x152@2x.png",
"idiom": "universal",
"scale": "2x",
"size": "152x152"
"filename" : "icon_76x76@2x.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "76x76"
},
{
"filename": "Icon_167x167@2x.png",
"idiom": "universal",
"scale": "2x",
"size": "167x167"
"filename" : "icon_83.5x83.5@2x.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "83.5x83.5"
},
{
"filename": "Icon_180x180@3x.png",
"idiom": "universal",
"scale": "3x",
"size": "180x180"
"filename" : "icon_1024x1024.png",
"idiom" : "ios-marketing",
"scale" : "1x",
"size" : "1024x1024"
},
{
"filename": "Icon_192x192@3x.png",
"idiom": "universal",
"scale": "3x",
"size": "192x192"
"filename" : "icon_114x114@3x.png",
"idiom" : "universal",
"scale" : "3x",
"size" : "114x114"
},
{
"filename": "Icon-App-iTunes.png",
"idiom": "ios-marketing",
"scale": "1x",
"size": "1024x1024"
"filename" : "icon_120x120@2x.png",
"idiom" : "universal",
"scale" : "2x",
"size" : "120x120"
},
{
"filename" : "icon_128x128@2x.png",
"idiom" : "universal",
"scale" : "2x",
"size" : "128x128"
},
{
"filename" : "icon_136x136@2x.png",
"idiom" : "universal",
"scale" : "2x",
"size" : "136x136"
},
{
"filename" : "icon_152x152@2x.png",
"idiom" : "universal",
"scale" : "2x",
"size" : "152x152"
},
{
"filename" : "icon_167x167@2x.png",
"idiom" : "universal",
"scale" : "2x",
"size" : "167x167"
},
{
"filename" : "icon_192x192@3x.png",
"idiom" : "universal",
"scale" : "3x",
"size" : "192x192"
}
],
"info": {
"author": "me.voidspace",
"version": 1
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 991 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

View file

Before

Width:  |  Height:  |  Size: 265 KiB

After

Width:  |  Height:  |  Size: 265 KiB

View file

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View file

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View file

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View file

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View file

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View file

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View file

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View file

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View file

Before

Width:  |  Height:  |  Size: 3 KiB

After

Width:  |  Height:  |  Size: 3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

View file

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View file

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View file

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View file

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

View file

@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<device id="retina6_12" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
@ -14,12 +16,14 @@
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
<rect key="frame" x="196.33333333333334" y="426" width="0.33333333333334281" height="0.33333333333331439"/>
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
@ -28,10 +32,10 @@
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
<point key="canvasLocation" x="80.916030534351137" y="264.08450704225356"/>
</scene>
</scenes>
<resources>
<image name="LaunchImage" width="168" height="185"/>
<image name="LaunchImage" width="0.3333333432674408" height="0.3333333432674408"/>
</resources>
</document>

View file

@ -7,7 +7,7 @@
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>ReCon</string>
<string>recon</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
@ -15,7 +15,7 @@
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>ReCon</string>
<string>recon</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
@ -32,7 +32,6 @@
<array>
<string>fetch</string>
<string>processing</string>
<string>remote-notification</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen.storyboard</string>
@ -41,15 +40,13 @@
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
</array>
</dict>
</plist>

View file

@ -4,7 +4,7 @@
<dict>
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)me.voidspace.recon</string>
<string>$(AppIdentifierPrefix)ch.isota.recon</string>
</array>
</dict>
</plist>

View file

@ -1,7 +1,7 @@
import 'dart:convert';
import 'package:recon/clients/api_client.dart';
import 'package:recon/models/cloud_variable.dart';
import 'package:OpenContacts/clients/api_client.dart';
import 'package:OpenContacts/models/cloud_variable.dart';
class CloudVariableApi {
static Future<CloudVariable> readCloudVariable(ApiClient client,

View file

@ -1,13 +1,37 @@
import 'dart:convert';
import 'package:recon/clients/api_client.dart';
import 'package:recon/models/users/contact.dart';
import 'package:OpenContacts/clients/api_client.dart';
import 'package:OpenContacts/models/users/friend.dart';
import 'package:OpenContacts/models/users/friend_status.dart';
import 'package:OpenContacts/models/users/user.dart';
import 'package:OpenContacts/models/users/user_profile.dart';
import 'package:OpenContacts/models/users/user_status.dart';
class ContactApi {
static Future<List<Contact>> getFriendsList(ApiClient client, {DateTime? lastStatusUpdate}) async {
static Future<List<Friend>> getFriendsList(ApiClient client, {DateTime? lastStatusUpdate}) async {
final response = await client.get("/users/${client.userId}/contacts${lastStatusUpdate != null ? "?lastStatusUpdate=${lastStatusUpdate.toUtc().toIso8601String()}" : ""}");
client.checkResponse(response);
final data = jsonDecode(response.body) as List;
return data.map((e) => Contact.fromMap(e)).toList();
return data.map((e) => Friend.fromMap(e)).toList();
}
static Future<void> addUserAsFriend(ApiClient client, {required User user}) async {
final friend = Friend(
id: user.id,
username: user.username,
ownerId: client.userId,
userStatus: UserStatus.empty(),
userProfile: UserProfile.empty(),
contactStatus: FriendStatus.accepted,
latestMessageTime: DateTime.now(),
);
final body = jsonEncode(friend.toMap(shallow: true));
final response = await client.put("/users/${client.userId}/contacts/${user.id}", body: body);
client.checkResponse(response);
}
static Future<void> removeUserAsFriend(ApiClient client, {required User user}) async {
final response = await client.delete("/users/${client.userId}/friends/${user.id}");
client.checkResponse(response);
}
}

View file

@ -3,10 +3,10 @@ import 'dart:convert';
import 'package:http/http.dart' as http;
class GithubApi {
static const baseUrl = "https://api.github.com";
static const baseUrl = "https://git.mrdab.vore.media/api/v1";
static Future<String> getLatestTagName() async {
final response = await http.get(Uri.parse("$baseUrl/repos/Nutcake/ReCon/releases?per_page=1"));
final response = await http.get(Uri.parse("$baseUrl/repos/ThatOneJackalGuy/OpenContacts/releases?per_page=1"));
if (response.statusCode != 200) return "";
final body = jsonDecode(response.body) as List;
if (body.isEmpty) return "";

View file

@ -1,7 +1,7 @@
import 'dart:convert';
import 'package:recon/clients/api_client.dart';
import 'package:recon/models/message.dart';
import 'package:OpenContacts/clients/api_client.dart';
import 'package:OpenContacts/models/message.dart';
class MessageApi {
static Future<List<Message>> getUserMessages(ApiClient client, {String userId = "", DateTime? fromTime,

View file

@ -3,16 +3,16 @@ import 'dart:io';
import 'dart:math';
import 'dart:typed_data';
import 'package:collection/collection.dart';
import 'package:recon/models/records/asset_digest.dart';
import 'package:recon/models/records/json_template.dart';
import 'package:OpenContacts/models/records/asset_digest.dart';
import 'package:OpenContacts/models/records/json_template.dart';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:recon/clients/api_client.dart';
import 'package:recon/models/records/asset_upload_data.dart';
import 'package:recon/models/records/resonite_db_asset.dart';
import 'package:recon/models/records/preprocess_status.dart';
import 'package:recon/models/records/record.dart';
import 'package:OpenContacts/clients/api_client.dart';
import 'package:OpenContacts/models/records/asset_upload_data.dart';
import 'package:OpenContacts/models/records/resonite_db_asset.dart';
import 'package:OpenContacts/models/records/preprocess_status.dart';
import 'package:OpenContacts/models/records/record.dart';
import 'package:http_parser/http_parser.dart';
import 'package:path/path.dart';

View file

@ -1,7 +1,7 @@
import 'dart:convert';
import 'package:recon/clients/api_client.dart';
import 'package:recon/models/session.dart';
import 'package:OpenContacts/clients/api_client.dart';
import 'package:OpenContacts/models/session.dart';
class SessionApi {
static Future<Session> getSession(ApiClient client, {required String sessionId}) async {

View file

@ -1,9 +1,9 @@
import 'dart:convert';
import 'package:recon/clients/api_client.dart';
import 'package:recon/models/personal_profile.dart';
import 'package:recon/models/users/user.dart';
import 'package:recon/models/users/user_status.dart';
import 'package:OpenContacts/clients/api_client.dart';
import 'package:OpenContacts/models/personal_profile.dart';
import 'package:OpenContacts/models/users/user.dart';
import 'package:OpenContacts/models/users/user_status.dart';
class UserApi {
static Future<Iterable<User>> searchUsers(ApiClient client, {required String needle}) async {

View file

@ -1,4 +1,4 @@
import 'package:recon/config.dart';
import 'package:OpenContacts/config.dart';
import 'package:flutter/material.dart';
import 'package:path/path.dart' as p;
import 'package:html/parser.dart' as htmlparser;

View file

@ -1,8 +1,8 @@
import 'package:recon/clients/api_client.dart';
import 'package:recon/clients/notification_client.dart';
import 'package:recon/clients/settings_client.dart';
import 'package:recon/models/authentication_data.dart';
import 'package:OpenContacts/clients/api_client.dart';
import 'package:OpenContacts/clients/notification_client.dart';
import 'package:OpenContacts/clients/settings_client.dart';
import 'package:OpenContacts/models/authentication_data.dart';
import 'package:flutter/material.dart';
class ClientHolder extends InheritedWidget {

View file

@ -3,7 +3,7 @@ import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:http/http.dart' as http;
import 'package:recon/models/authentication_data.dart';
import 'package:OpenContacts/models/authentication_data.dart';
import 'package:logging/logging.dart';
import 'package:uuid/uuid.dart';

View file

@ -4,9 +4,9 @@ import 'package:ffmpeg_kit_flutter_audio/ffmpeg_kit.dart';
import 'package:http/http.dart' as http;
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:recon/auxiliary.dart';
import 'package:recon/clients/api_client.dart';
import 'package:recon/models/message.dart';
import 'package:OpenContacts/auxiliary.dart';
import 'package:OpenContacts/clients/api_client.dart';
import 'package:OpenContacts/models/message.dart';
class AudioCacheClient {
final Future<Directory> _directoryFuture = getTemporaryDirectory();

View file

@ -1,10 +1,10 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:recon/apis/record_api.dart';
import 'package:recon/clients/api_client.dart';
import 'package:recon/models/inventory/resonite_directory.dart';
import 'package:recon/models/records/record.dart';
import 'package:OpenContacts/apis/record_api.dart';
import 'package:OpenContacts/clients/api_client.dart';
import 'package:OpenContacts/models/inventory/resonite_directory.dart';
import 'package:OpenContacts/models/records/record.dart';
enum SortMode {
name,

View file

@ -1,28 +1,25 @@
import 'dart:async';
import 'package:recon/apis/contact_api.dart';
import 'package:recon/apis/message_api.dart';
import 'package:recon/apis/session_api.dart';
import 'package:recon/apis/user_api.dart';
import 'package:recon/clients/api_client.dart';
import 'package:recon/clients/notification_client.dart';
import 'package:recon/clients/settings_client.dart';
import 'package:recon/crypto_helper.dart';
import 'package:recon/hub_manager.dart';
import 'package:recon/models/broadcast_group.dart';
import 'package:recon/models/hub_events.dart';
import 'package:recon/models/message.dart';
import 'package:recon/models/session.dart';
import 'package:recon/models/users/contact.dart';
import 'package:recon/models/users/contact_status.dart';
import 'package:recon/models/users/online_status.dart';
import 'package:recon/models/users/user.dart';
import 'package:recon/models/users/user_status.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:logging/logging.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:OpenContacts/apis/contact_api.dart';
import 'package:OpenContacts/apis/message_api.dart';
import 'package:OpenContacts/apis/session_api.dart';
import 'package:OpenContacts/apis/user_api.dart';
import 'package:OpenContacts/clients/api_client.dart';
import 'package:OpenContacts/clients/notification_client.dart';
import 'package:OpenContacts/clients/settings_client.dart';
import 'package:OpenContacts/crypto_helper.dart';
import 'package:OpenContacts/hub_manager.dart';
import 'package:OpenContacts/models/hub_events.dart';
import 'package:OpenContacts/models/message.dart';
import 'package:OpenContacts/models/session.dart';
import 'package:OpenContacts/models/users/friend.dart';
import 'package:OpenContacts/models/users/online_status.dart';
import 'package:OpenContacts/models/users/user_status.dart';
class MessagingClient extends ChangeNotifier {
static const Duration _autoRefreshDuration = Duration(seconds: 10);
@ -32,7 +29,7 @@ class MessagingClient extends ChangeNotifier {
static const String _lastUpdateKey = "__last-update-time";
final ApiClient _apiClient;
final List<Contact> _sortedFriendsCache = []; // Keep a sorted copy so as to not have to sort during build()
final List<Friend> _sortedFriendsCache = []; // Keep a sorted copy so as to not have to sort during build()
final Map<String, MessageCache> _messageCache = {};
final Map<String, List<Message>> _unreads = {};
final Logger _logger = Logger("Messaging");
@ -41,7 +38,7 @@ class MessagingClient extends ChangeNotifier {
final Map<String, Session> _sessionMap = {};
final Set<String> _knownSessionKeys = {};
final SettingsClient _settingsClient;
Contact? selectedFriend;
Friend? selectedFriend;
Timer? _statusHeartbeat;
Timer? _autoRefresh;
@ -79,16 +76,16 @@ class MessagingClient extends ChangeNotifier {
String? get initStatus => _initStatus;
List<Contact> get cachedFriends => _sortedFriendsCache;
List<Friend> get cachedFriends => _sortedFriendsCache;
List<Message> getUnreadsForContact(Contact contact) => _unreads[contact.id] ?? [];
List<Message> getUnreadsForFriend(Friend friend) => _unreads[friend.id] ?? [];
bool contactHasUnreads(Contact contact) => _unreads.containsKey(contact.id);
bool friendHasUnreads(Friend friend) => _unreads.containsKey(friend.id);
bool messageIsUnread(Message message) =>
_unreads[message.senderId]?.any((element) => element.id == message.id) ?? false;
Contact? getAsContact(String userId) => Contact.fromMapOrNull(Hive.box(_messageBoxKey).get(userId));
Friend? getAsFriend(String userId) => Friend.fromMapOrNull(Hive.box(_messageBoxKey).get(userId));
MessageCache? getUserMessageCache(String userId) => _messageCache[userId];
@ -110,7 +107,7 @@ class MessagingClient extends ChangeNotifier {
final friends = await ContactApi.getFriendsList(_apiClient, lastStatusUpdate: lastUpdateUtc);
for (final friend in friends) {
await _updateContactLocal(friend);
await _updateContact(friend);
}
_initStatus = "";
@ -132,7 +129,7 @@ class MessagingClient extends ChangeNotifier {
clearUnreadsForUser(batch.senderId);
}
Future<void> setOnlineStatus(OnlineStatus status, {String? target}) async {
Future<void> setOnlineStatus(OnlineStatus status) async {
final pkginfo = await PackageInfo.fromPlatform();
final now = DateTime.now();
_userStatus = _userStatus.copyWith(
@ -149,16 +146,15 @@ class MessagingClient extends ChangeNotifier {
arguments: [
_userStatus.toMap(),
{
"group": target == null ? BroadcastGroup.allContacts.index : BroadcastGroup.specificContacts.index,
"targetIds": target,
"group": 1,
"targetIds": null,
}
],
);
if (target == null) {
final self = getAsContact(_apiClient.userId);
if (self != null) {
await _updateContactLocal(self.copyWith(userStatus: _userStatus));
}
final self = getAsFriend(_apiClient.userId);
if (self != null) {
await _updateContact(self.copyWith(userStatus: _userStatus));
}
notifyListeners();
}
@ -173,10 +169,7 @@ class MessagingClient extends ChangeNotifier {
}
messages.sort();
_sortFriendsCache();
_notificationClient.showUnreadMessagesNotification(
messages.reversed,
getAsContact,
);
_notificationClient.showUnreadMessagesNotification(messages.reversed);
notifyListeners();
}
@ -211,10 +204,10 @@ class MessagingClient extends ChangeNotifier {
}
Future<void> updateFriendStatus(String userId) async {
final friend = getAsContact(userId);
final friend = getAsFriend(userId);
if (friend == null) return;
final newStatus = await UserApi.getUserStatus(_apiClient, userId: userId);
await _updateContactLocal(friend.copyWith(userStatus: newStatus));
await _updateContact(friend.copyWith(userStatus: newStatus));
notifyListeners();
}
@ -223,30 +216,6 @@ class MessagingClient extends ChangeNotifier {
notifyListeners();
}
void addUserAsFriend(User user) {
_hubManager.send(
"UpdateContact",
arguments: [
user.asContactRequest(
ownerId: _apiClient.userId,
contactStatus: ContactStatus.accepted,
)
],
);
}
void removeUserAsFriend(User user) {
_hubManager.send(
"UpdateContact",
arguments: [
user.asContactRequest(
ownerId: _apiClient.userId,
contactStatus: ContactStatus.ignored,
)
],
);
}
Future<void> _refreshUnreads() async {
try {
final unreadMessages = await MessageApi.getUserMessages(_apiClient, unreadOnly: true);
@ -254,22 +223,50 @@ class MessagingClient extends ChangeNotifier {
} catch (_) {}
}
// Calculate online status value, with 'headless' between 'busy' and 'offline'
double getOnlineStatusValue(Friend friend) {
// Adjusting values to ensure correct placement of 'headless'
if (friend.isHeadless) return 2.5;
switch (friend.userStatus.onlineStatus) {
case OnlineStatus.sociable:
return 0;
case OnlineStatus.online:
return 1;
case OnlineStatus.away:
return 2;
case OnlineStatus.busy:
return 3;
case OnlineStatus.invisible:
return 3.5;
case OnlineStatus.offline:
default:
return 4;
}
}
void _sortFriendsCache() {
_sortedFriendsCache.sort((a, b) {
if (a.isContactRequest != b.isContactRequest) {
return a.isContactRequest ? -1 : 1;
// Check for unreads and sort by latest message time if either has unreads
bool aHasUnreads = friendHasUnreads(a);
bool bHasUnreads = friendHasUnreads(b);
if (aHasUnreads || bHasUnreads) {
if (aHasUnreads && bHasUnreads) {
return -a.latestMessageTime.compareTo(b.latestMessageTime);
}
return aHasUnreads ? -1 : 1;
}
var aVal = contactHasUnreads(a) ? -3 : 0;
var bVal = contactHasUnreads(b) ? -3 : 0;
int onlineStatusComparison = getOnlineStatusValue(a).compareTo(getOnlineStatusValue(b));
if (onlineStatusComparison != 0) {
return onlineStatusComparison;
}
aVal -= a.latestMessageTime.compareTo(b.latestMessageTime);
aVal += a.userStatus.onlineStatus.compareTo(b.userStatus.onlineStatus) * 2;
return aVal.compareTo(bVal);
return -a.latestMessageTime.compareTo(b.latestMessageTime);
});
}
Future<void> _updateContactLocal(Contact friend) async {
Future<void> _updateContact(Friend friend) async {
final box = Hive.box(_messageBoxKey);
box.put(friend.id, friend.toMap());
final lastStatusUpdate = box.get(_lastUpdateKey);
@ -301,16 +298,15 @@ class MessagingClient extends ChangeNotifier {
_hubManager.setHandler(EventTarget.receiveStatusUpdate, _onReceiveStatusUpdate);
_hubManager.setHandler(EventTarget.receiveSessionUpdate, _onReceiveSessionUpdate);
_hubManager.setHandler(EventTarget.removeSession, _onRemoveSession);
_hubManager.setHandler(EventTarget.contactAddedOrUpdated, _onContactAddedOrUpdated);
await _hubManager.start();
_hubManager.send(
"InitializeStatus",
responseHandler: (Map data) async {
final rawContacts = data["contacts"] as List;
final contacts = rawContacts.map((e) => Contact.fromMap(e)).toList();
final contacts = rawContacts.map((e) => Friend.fromMap(e)).toList();
for (final contact in contacts) {
await _updateContactLocal(contact);
await _updateContact(contact);
}
_initStatus = "";
notifyListeners();
@ -331,51 +327,6 @@ class MessagingClient extends ChangeNotifier {
return _sessionMap.map((key, value) => MapEntry(CryptoHelper.idHash(value.id + salt), value));
}
void _onContactAddedOrUpdated(List args) {
bool shouldUpdateRequestCount = false;
bool shouldRegisterNewContact = false;
for (var request in args) {
final newContact = Contact.fromMap(request);
Contact? existingContact = getAsContact(newContact.id);
if (existingContact != null) {
if (!existingContact.isAccepted && newContact.isAccepted) {
shouldRegisterNewContact = true;
}
if (newContact.isContactRequest != existingContact.isContactRequest) {
shouldUpdateRequestCount = true;
}
} else {
if (newContact.isAccepted) {
shouldRegisterNewContact = true;
}
if (newContact.isContactRequest) {
shouldUpdateRequestCount = true;
}
}
_updateContactLocal(newContact);
if (shouldRegisterNewContact) {
final isInvisible = userStatus.onlineStatus == OnlineStatus.invisible;
_hubManager.send("ListenOnContact", arguments: [newContact.id]);
_hubManager.send("RequestStatus", arguments: [newContact.id, isInvisible]);
if (!isInvisible) {
_hubManager.send(
"BroadcastStatus",
arguments: [
userStatus.toMap(shallow: true),
{
"group": BroadcastGroup.specificContacts.index,
"targetIds": newContact.id,
},
],
);
}
}
if (shouldUpdateRequestCount) {
_notificationClient.showContactRequestNotification(newContact);
}
}
}
void _onMessageSent(List args) {
final msg = args[0];
final message = Message.fromMap(msg, withState: MessageState.sent);
@ -418,9 +369,9 @@ class MessagingClient extends ChangeNotifier {
decodedSessions: status.sessions
.map((e) => sessionMap[e.sessionHash] ?? Session.none().copyWith(accessLevel: e.accessLevel))
.toList());
final friend = getAsContact(statusUpdate["userId"])?.copyWith(userStatus: status);
final friend = getAsFriend(statusUpdate["userId"])?.copyWith(userStatus: status);
if (friend != null) {
_updateContactLocal(friend);
_updateContact(friend);
}
for (var session in status.sessions) {
if (session.broadcastKey != null && _knownSessionKeys.add(session.broadcastKey ?? "")) {

View file

@ -2,10 +2,9 @@ import 'dart:convert';
import 'package:collection/collection.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart' as fln;
import 'package:recon/auxiliary.dart';
import 'package:recon/models/message.dart';
import 'package:recon/models/session.dart';
import 'package:recon/models/users/contact.dart';
import 'package:OpenContacts/auxiliary.dart';
import 'package:OpenContacts/models/message.dart';
import 'package:OpenContacts/models/session.dart';
class NotificationChannel {
final String id;
@ -27,16 +26,16 @@ class NotificationClient {
android: fln.AndroidInitializationSettings("ic_notification"),
iOS: fln.DarwinInitializationSettings(),
macOS: fln.DarwinInitializationSettings(),
linux: fln.LinuxInitializationSettings(defaultActionName: "Open ReCon"),
linux: fln.LinuxInitializationSettings(defaultActionName: "Open OpenContacts"),
));
Future<void> showUnreadMessagesNotification(Iterable<Message> messages, Contact? Function(String userId) contactGetter) async {
Future<void> showUnreadMessagesNotification(Iterable<Message> messages) async {
if (messages.isEmpty) return;
final bySender = groupBy(messages, (p0) => p0.senderId);
for (final entry in bySender.entries) {
final contact = contactGetter(entry.key);
final uname = contact?.contactUsername ?? "Unknown";
final uname = entry.key.stripUid();
await _notifier.show(
uname.hashCode,
null,
@ -94,13 +93,4 @@ class NotificationClient {
);
}
}
Future<void> showContactRequestNotification(Contact contact) async {
await _notifier.show(
contact.contactUsername.hashCode,
"New Contact request",
"User ${contact.contactUsername} wants to be your friend.",
null
);
}
}

View file

@ -1,8 +1,8 @@
import 'package:collection/collection.dart';
import 'package:recon/apis/session_api.dart';
import 'package:recon/clients/api_client.dart';
import 'package:recon/clients/settings_client.dart';
import 'package:recon/models/session.dart';
import 'package:OpenContacts/apis/session_api.dart';
import 'package:OpenContacts/clients/api_client.dart';
import 'package:OpenContacts/clients/settings_client.dart';
import 'package:OpenContacts/models/session.dart';
import 'package:flutter/foundation.dart';
class SessionClient extends ChangeNotifier {

View file

@ -1,6 +1,6 @@
import 'dart:convert';
import 'package:recon/models/settings.dart';
import 'package:OpenContacts/models/settings.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';

View file

@ -3,8 +3,8 @@ import 'dart:io';
import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart';
import 'package:recon/config.dart';
import 'package:recon/models/hub_events.dart';
import 'package:OpenContacts/config.dart';
import 'package:OpenContacts/models/hub_events.dart';
import 'package:logging/logging.dart';
import 'package:uuid/uuid.dart';
@ -105,13 +105,12 @@ class HubManager {
}
void _handleInvocation(body) async {
_logger.info(body);
final target = EventTarget.parse(body["target"]);
final args = body["arguments"] ?? [];
final handler = _handlers[target];
if (handler == null) {
_logger.warning("Unhandled event received");
if (kDebugMode) _logger.warning("Invocation target: ${body["target"]}, args:\n$args");
if (kDebugMode) _logger.warning("Invocation target: ${target.name}, args:\n$args");
return;
}
handler(args);
@ -133,9 +132,6 @@ class HubManager {
}
void dispose() {
_handlers.clear();
_responseHandlers.clear();
_wsChannel?.close();
_wsChannel = null;
}
}

View file

@ -1,29 +0,0 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class LifecycleEventHandler extends WidgetsBindingObserver {
final AsyncCallback? resumeCallBack;
final AsyncCallback? suspendingCallBack;
LifecycleEventHandler({
this.resumeCallBack,
this.suspendingCallBack,
});
@override
void didChangeAppLifecycleState(AppLifecycleState state) async {
super.didChangeAppLifecycleState(state);
switch (state) {
case AppLifecycleState.resumed:
await resumeCallBack?.call();
break;
case AppLifecycleState.inactive:
case AppLifecycleState.paused:
case AppLifecycleState.detached:
await suspendingCallBack?.call();
break;
default:
break;
}
}
}

View file

@ -13,17 +13,17 @@ import 'package:intl/intl.dart';
import 'package:logging/logging.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:provider/provider.dart';
import 'package:recon/apis/github_api.dart';
import 'package:recon/client_holder.dart';
import 'package:recon/clients/api_client.dart';
import 'package:recon/clients/inventory_client.dart';
import 'package:recon/clients/messaging_client.dart';
import 'package:recon/clients/session_client.dart';
import 'package:recon/clients/settings_client.dart';
import 'package:recon/models/sem_ver.dart';
import 'package:recon/widgets/homepage.dart';
import 'package:recon/widgets/login_screen.dart';
import 'package:recon/widgets/update_notifier.dart';
import 'package:OpenContacts/apis/github_api.dart';
import 'package:OpenContacts/client_holder.dart';
import 'package:OpenContacts/clients/api_client.dart';
import 'package:OpenContacts/clients/inventory_client.dart';
import 'package:OpenContacts/clients/messaging_client.dart';
import 'package:OpenContacts/clients/session_client.dart';
import 'package:OpenContacts/clients/settings_client.dart';
import 'package:OpenContacts/models/sem_ver.dart';
import 'package:OpenContacts/widgets/homepage.dart';
import 'package:OpenContacts/widgets/login_screen.dart';
import 'package:OpenContacts/widgets/update_notifier.dart';
import 'models/authentication_data.dart';
@ -59,20 +59,20 @@ void main() async {
// Ignore
}
runApp(ReCon(settingsClient: settingsClient, cachedAuthentication: cachedAuth));
runApp(recon(settingsClient: settingsClient, cachedAuthentication: cachedAuth));
}
class ReCon extends StatefulWidget {
const ReCon({required this.settingsClient, required this.cachedAuthentication, super.key});
class recon extends StatefulWidget {
const recon({required this.settingsClient, required this.cachedAuthentication, super.key});
final SettingsClient settingsClient;
final AuthenticationData cachedAuthentication;
@override
State<ReCon> createState() => _ReConState();
State<recon> createState() => _reconState();
}
class _ReConState extends State<ReCon> {
class _reconState extends State<recon> {
final Typography _typography = Typography.material2021(platform: defaultTargetPlatform);
final ReceivePort _port = ReceivePort();
late AuthenticationData _authData = widget.cachedAuthentication;
@ -164,8 +164,8 @@ class _ReConState extends State<ReCon> {
},
child: DynamicColorBuilder(
builder: (ColorScheme? lightDynamic, ColorScheme? darkDynamic) => MaterialApp(
debugShowCheckedModeBanner: false,
title: 'ReCon',
debugShowCheckedModeBanner: true,
title: 'OpenContacts',
theme: ThemeData(
useMaterial3: true,
textTheme: _typography.black,

View file

@ -1,8 +0,0 @@
enum BroadcastGroup
{
public,
allContacts,
specificContacts,
broadcastKey,
connectionIds,
}

View file

@ -1,4 +1,4 @@
import 'package:recon/auxiliary.dart';
import 'package:OpenContacts/auxiliary.dart';
class CloudVariable {
final String ownerId;

View file

@ -16,9 +16,7 @@ enum EventTarget {
messagesRead,
receiveSessionUpdate,
removeSession,
receiveStatusUpdate,
sendStatusToUser,
contactAddedOrUpdated;
receiveStatusUpdate;
factory EventTarget.parse(String? text) {
if (text == null) return EventTarget.unknown;

View file

@ -1,5 +1,5 @@
import 'package:collection/collection.dart';
import 'package:recon/models/records/record.dart';
import 'package:OpenContacts/models/records/record.dart';
class ResoniteDirectory {
static const rootName = "Inventory";

View file

@ -1,10 +1,10 @@
import 'dart:async';
import 'dart:developer';
import 'package:recon/clients/api_client.dart';
import 'package:recon/apis/message_api.dart';
import 'package:recon/auxiliary.dart';
import 'package:recon/string_formatter.dart';
import 'package:OpenContacts/clients/api_client.dart';
import 'package:OpenContacts/apis/message_api.dart';
import 'package:OpenContacts/auxiliary.dart';
import 'package:OpenContacts/string_formatter.dart';
import 'package:uuid/uuid.dart';
enum MessageType {

View file

@ -1,6 +1,6 @@
import 'package:recon/auxiliary.dart';
import 'package:recon/models/users/entitlement.dart';
import 'package:recon/models/users/user_profile.dart';
import 'package:OpenContacts/auxiliary.dart';
import 'package:OpenContacts/models/users/entitlement.dart';
import 'package:OpenContacts/models/users/user_profile.dart';
class PersonalProfile {
final String id;

View file

@ -1,5 +1,5 @@
import 'package:recon/models/records/resonite_db_asset.dart';
import 'package:OpenContacts/models/records/resonite_db_asset.dart';
class AssetDiff extends ResoniteDBAsset{
final Diff state;

View file

@ -1,7 +1,7 @@
import 'dart:typed_data';
import 'package:recon/models/records/resonite_db_asset.dart';
import 'package:OpenContacts/models/records/resonite_db_asset.dart';
import 'package:path/path.dart';
class AssetDigest {

View file

@ -1,4 +1,4 @@
import 'package:recon/models/records/asset_diff.dart';
import 'package:OpenContacts/models/records/asset_diff.dart';
enum RecordPreprocessState
{

View file

@ -1,8 +1,8 @@
import 'package:recon/auxiliary.dart';
import 'package:recon/models/message.dart';
import 'package:recon/models/records/asset_digest.dart';
import 'package:recon/models/records/resonite_db_asset.dart';
import 'package:recon/string_formatter.dart';
import 'package:OpenContacts/auxiliary.dart';
import 'package:OpenContacts/models/message.dart';
import 'package:OpenContacts/models/records/asset_digest.dart';
import 'package:OpenContacts/models/records/resonite_db_asset.dart';
import 'package:OpenContacts/string_formatter.dart';
import 'package:flutter/material.dart';
import 'package:uuid/uuid.dart';

View file

@ -1,4 +1,4 @@
import 'package:recon/string_formatter.dart';
import 'package:OpenContacts/string_formatter.dart';
class Session {
final String id;
@ -131,6 +131,7 @@ class Session {
enum SessionAccessLevel {
unknown,
private,
lan,
contacts,
contactsPlus,
registeredUsers,
@ -139,6 +140,7 @@ enum SessionAccessLevel {
static const _readableNamesMap = {
SessionAccessLevel.unknown: "Unknown",
SessionAccessLevel.private: "Private",
SessionAccessLevel.lan: "LAN",
SessionAccessLevel.contacts: "Contacts only",
SessionAccessLevel.contactsPlus: "Contacts+",
SessionAccessLevel.registeredUsers: "Registered users",

View file

@ -1,4 +1,4 @@
import 'package:recon/models/session.dart';
import 'package:OpenContacts/models/session.dart';
import 'package:intl/intl.dart';
class SessionMetadata {

View file

@ -1,7 +1,7 @@
import 'dart:convert';
import 'package:recon/models/sem_ver.dart';
import 'package:recon/models/users/online_status.dart';
import 'package:OpenContacts/models/sem_ver.dart';
import 'package:OpenContacts/models/users/online_status.dart';
import 'package:flutter/material.dart';
import 'package:uuid/uuid.dart';

View file

@ -1,106 +0,0 @@
import 'package:recon/auxiliary.dart';
import 'package:recon/models/users/user_profile.dart';
import 'package:recon/models/users/contact_status.dart';
import 'package:recon/models/users/online_status.dart';
import 'package:recon/models/users/user_status.dart';
class Contact implements Comparable {
static const _emptyId = "-1";
static const _resoniteBotId = "U-Resonite";
final String id;
final String contactUsername;
final String ownerId;
final bool isAccepted;
final bool isMigrated;
final bool isCounterpartMigrated;
final UserStatus userStatus;
final UserProfile userProfile;
final ContactStatus contactStatus;
final DateTime latestMessageTime;
const Contact({required this.id, required this.contactUsername, required this.ownerId, required this.isAccepted,
required this.isMigrated, required this.isCounterpartMigrated, required this.userStatus, required this.userProfile,
required this.contactStatus, required this.latestMessageTime,
});
bool get isHeadless => userStatus.outputDevice == "Headless";
factory Contact.fromMap(Map map) {
var userStatus = map["userStatus"] == null ? UserStatus.empty() : UserStatus.fromMap(map["userStatus"]);
return Contact(
id: map["id"],
contactUsername: map["contactUsername"],
ownerId: map["ownerId"] ?? map["id"],
isAccepted: map["isAccepted"] ?? false,
isMigrated: map["isMigrated"] ?? false,
isCounterpartMigrated: map["isCounterpartMigrated"] ?? false,
// Resonite bot status is always offline but should be displayed as online
userStatus: map["id"] == _resoniteBotId ? userStatus.copyWith(onlineStatus: OnlineStatus.online) : userStatus,
userProfile: UserProfile.fromMap(map["profile"] ?? {}),
contactStatus: ContactStatus.fromString(map["contactStatus"]),
latestMessageTime: map["latestMessageTime"] == null
? DateTime.fromMillisecondsSinceEpoch(0) : DateTime.parse(map["latestMessageTime"]),
);
}
static Contact? fromMapOrNull(Map? map) {
if (map == null) return null;
return Contact.fromMap(map);
}
factory Contact.empty() {
return Contact(
id: _emptyId,
contactUsername: "",
ownerId: "",
isAccepted: false,
isMigrated: false,
isCounterpartMigrated: false,
userStatus: UserStatus.empty(),
userProfile: UserProfile.empty(),
contactStatus: ContactStatus.none,
latestMessageTime: DateTimeX.epoch
);
}
bool get isEmpty => id == _emptyId;
bool get isPartiallyMigrated => isMigrated && !isCounterpartMigrated;
bool get isContactRequest => !isPartiallyMigrated && isAccepted && contactStatus == ContactStatus.requested;
Contact copyWith({
String? id, String? contactUsername, String? ownerId, UserStatus? userStatus, bool? isAccepted, bool? isMigrated,
bool? isCounterpartMigrated, UserProfile? userProfile, ContactStatus? contactStatus, DateTime? latestMessageTime}) {
return Contact(
id: id ?? this.id,
contactUsername: contactUsername ?? this.contactUsername,
ownerId: ownerId ?? this.ownerId,
isAccepted: isAccepted ?? this.isAccepted,
isMigrated: isMigrated ?? this.isMigrated,
isCounterpartMigrated: isCounterpartMigrated ?? this.isCounterpartMigrated,
userStatus: userStatus ?? this.userStatus,
userProfile: userProfile ?? this.userProfile,
contactStatus: contactStatus ?? this.contactStatus,
latestMessageTime: latestMessageTime ?? this.latestMessageTime,
);
}
Map toMap({bool shallow=false}) {
return {
"id": id,
"contactUsername": contactUsername,
"ownerId": ownerId,
"isAccepted": isAccepted,
"isMigrated": isMigrated,
"isCounterpartMigrated": isCounterpartMigrated,
"userStatus": userStatus.toMap(shallow: shallow),
"profile": userProfile.toMap(),
"contactStatus": contactStatus.name,
"latestMessageTime": latestMessageTime.toIso8601String(),
};
}
@override
int compareTo(covariant Contact other) {
return contactUsername.compareTo(other.contactUsername);
}
}

View file

@ -1,14 +0,0 @@
enum ContactStatus {
none,
searchResult,
requested,
ignored,
blocked,
accepted;
factory ContactStatus.fromString(String text) {
return ContactStatus.values.firstWhere((element) => element.name.toLowerCase() == text.toLowerCase(),
orElse: () => ContactStatus.none,
);
}
}

View file

@ -1,4 +1,4 @@
import 'package:recon/auxiliary.dart';
import 'package:OpenContacts/auxiliary.dart';
class Entitlement {
Entitlement();

View file

@ -0,0 +1,109 @@
import 'package:OpenContacts/auxiliary.dart';
import 'package:OpenContacts/models/users/friend_status.dart';
import 'package:OpenContacts/models/users/online_status.dart';
import 'package:OpenContacts/models/users/user_profile.dart';
import 'package:OpenContacts/models/users/user_status.dart';
class Friend implements Comparable {
static const _emptyId = "-1";
static const _resoniteBotId = "U-Resonite";
final String id;
final String username;
final String ownerId;
final UserStatus userStatus;
final UserProfile userProfile;
final FriendStatus contactStatus;
final DateTime latestMessageTime;
const Friend({
required this.id,
required this.username,
required this.ownerId,
required this.userStatus,
required this.userProfile,
required this.contactStatus,
required this.latestMessageTime,
});
bool get isHeadless => userStatus.sessionType == UserSessionType.headless;
bool get isBot => userStatus.sessionType == UserSessionType.bot || id == _resoniteBotId;
bool get isOffline =>
(userStatus.onlineStatus == OnlineStatus.offline || userStatus.onlineStatus == OnlineStatus.invisible) &&
!isBot &&
!isHeadless;
bool get isOnline => !isOffline;
factory Friend.fromMap(Map map) {
var userStatus = map["userStatus"] == null ? UserStatus.empty() : UserStatus.fromMap(map["userStatus"]);
return Friend(
id: map["id"],
username: map["contactUsername"],
ownerId: map["ownerId"] ?? map["id"],
// Resonite bot status is always offline but should be displayed as online
userStatus: map["id"] == _resoniteBotId ? userStatus.copyWith(onlineStatus: OnlineStatus.online) : userStatus,
userProfile: UserProfile.fromMap(map["profile"] ?? {}),
contactStatus: FriendStatus.fromString(map["contactStatus"]),
latestMessageTime: map["latestMessageTime"] == null
? DateTime.fromMillisecondsSinceEpoch(0)
: DateTime.parse(map["latestMessageTime"]),
);
}
static Friend? fromMapOrNull(Map? map) {
if (map == null) return null;
return Friend.fromMap(map);
}
factory Friend.empty() {
return Friend(
id: _emptyId,
username: "",
ownerId: "",
userStatus: UserStatus.empty(),
userProfile: UserProfile.empty(),
contactStatus: FriendStatus.none,
latestMessageTime: DateTimeX.epoch,
);
}
bool get isEmpty => id == _emptyId;
Friend copyWith(
{String? id,
String? username,
String? ownerId,
UserStatus? userStatus,
UserProfile? userProfile,
FriendStatus? contactStatus,
DateTime? latestMessageTime}) {
return Friend(
id: id ?? this.id,
username: username ?? this.username,
ownerId: ownerId ?? this.ownerId,
userStatus: userStatus ?? this.userStatus,
userProfile: userProfile ?? this.userProfile,
contactStatus: contactStatus ?? this.contactStatus,
latestMessageTime: latestMessageTime ?? this.latestMessageTime,
);
}
Map toMap({bool shallow = false}) {
return {
"id": id,
"contactUsername": username,
"ownerId": ownerId,
"userStatus": userStatus.toMap(shallow: shallow),
"profile": userProfile.toMap(),
"contactStatus": contactStatus.name,
"latestMessageTime": latestMessageTime.toIso8601String(),
};
}
@override
int compareTo(covariant Friend other) {
return username.compareTo(other.username);
}
}

View file

@ -0,0 +1,14 @@
enum FriendStatus {
none,
searchResult,
requested,
ignored,
blocked,
accepted;
factory FriendStatus.fromString(String text) {
return FriendStatus.values.firstWhere((element) => element.name.toLowerCase() == text.toLowerCase(),
orElse: () => FriendStatus.none,
);
}
}

View file

@ -5,26 +5,33 @@ enum OnlineStatus {
invisible,
away,
busy,
online;
online,
sociable;
static final List<Color> _colors = [
Colors.transparent,
Colors.transparent,
Colors.grey,
Colors.yellow,
Colors.red,
Colors.green,
Colors.blue,
];
Color color(BuildContext context) => this == OnlineStatus.offline || this == OnlineStatus.invisible ? Theme.of(context).colorScheme.onSurface : _colors[index];
Color color(BuildContext context) => this == OnlineStatus.offline || this == OnlineStatus.invisible
? Theme.of(context).colorScheme.onSecondaryContainer.withAlpha(150)
: _colors[index];
factory OnlineStatus.fromString(String? text) {
return OnlineStatus.values.firstWhere((element) => element.name.toLowerCase() == text?.toLowerCase(),
return OnlineStatus.values.firstWhere(
(element) => element.name.toLowerCase() == text?.toLowerCase(),
orElse: () => OnlineStatus.online,
);
}
int compareTo(OnlineStatus other) {
if (this == other) return 0;
if (this == OnlineStatus.sociable) return -1;
if (other == OnlineStatus.sociable) return 1;
if (this == OnlineStatus.online) return -1;
if (other == OnlineStatus.online) return 1;
if (this == OnlineStatus.away) return -1;

View file

@ -1,5 +1,4 @@
import 'package:recon/models/users/contact_status.dart';
import 'package:recon/models/users/user_profile.dart';
import 'package:OpenContacts/models/users/user_profile.dart';
class User {
final String id;
@ -32,13 +31,4 @@ class User {
"profile": userProfile?.toMap(),
};
}
Map asContactRequest({required String ownerId, required ContactStatus contactStatus}) {
return {
"ownerId": ownerId,
"id": id,
"contactUsername": username,
"contactStatus": ContactStatus.accepted.name,
};
}
}

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