Skip to content

Commit

Permalink
Device Settings, Intercom Integration and Improvements (#902)
Browse files Browse the repository at this point in the history
- [x] Move device settings to settings page
- [x] Move getDeviceInfo to device provider
- [x] Guides and support should be highlighted further
- [x] Improve the guides UI (dialogs look bad)
- [x] An individual item on device settings, about how to charge it,
opens a separate page with images and clear instructions (using
intercom)
- [x] This page above should also be accessible from device details page
below the battery indicator (using intercom)
- [x] Migrate AGP to 8+ and Proguard changes
- [x] Integrate intercom (with push notifications)
- [x] Add `need help? chat with us` option at the top in settings



https://github.com/user-attachments/assets/86a33f34-9f09-4db5-86b7-1e4c89e6e9e7



<!-- This is an auto-generated comment: release notes by OSS
Entelligence.AI -->
### Summary by Entelligence.AI

- New Feature: Introduced a separate page for device settings, enhancing
the UI and navigation flow.
- New Feature: Added a button to access specific device information and
a text button for navigating to device charging instructions.
- Refactor: Moved device settings related functions to `DeviceSettings`
widget, improving code modularity.
- New Feature: Enhanced `SupportPage` with `ExpansionTileCard` for
better presentation of firmware updates and bootloader support
information. Added links to guides for manual firmware and bootloader
updates.
- Chore: Updated Gradle distribution URL to version 8.0 and iOS platform
version to 15.0 for improved compatibility and feature availability.
- New Feature: Integrated Intercom SDK for chat support and push
notifications, providing a better user experience.
- Refactor: Added environment variables for Intercom configuration,
improving code maintainability and security.
<!-- end of auto-generated comment: release notes by OSS Entelligence.AI
-->
  • Loading branch information
josancamon19 committed Sep 24, 2024
2 parents fb24868 + def9628 commit f01db3f
Show file tree
Hide file tree
Showing 24 changed files with 769 additions and 294 deletions.
13 changes: 12 additions & 1 deletion app/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ if (keystorePropertiesFile.exists()) {

android {

buildFeatures {
buildConfig = true
}

namespace "com.friend.ios"


// ----- BEGIN flavorDimensions (autogenerated by flutter_flavorizr) -----
flavorDimensions += "flavor-type"

Expand Down Expand Up @@ -76,6 +83,8 @@ android {
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true
buildConfigField("String", "INTERCOM_APP_ID", "\"${System.getenv("intercom.app.id")}\"")
buildConfigField("String", "INTERCOM_ANDROID_API_KEY", "\"${System.getenv("intercom.android.api.key")}\"")
}

signingConfigs {
Expand Down Expand Up @@ -105,6 +114,7 @@ android {
shrinkResources true
}
debug{
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
minifyEnabled true
}
}
Expand All @@ -117,9 +127,10 @@ flutter {
}

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.10"
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation 'androidx.multidex:multidex:2.0.1'
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha3'
implementation 'io.intercom.android:intercom-sdk:latest.release'
}
27 changes: 27 additions & 0 deletions app/android/app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
# This is generated automatically by the Android Gradle plugin.
-dontwarn com.google.android.play.core.splitcompat.SplitCompatApplication
-dontwarn com.google.android.play.core.splitinstall.SplitInstallException
-dontwarn com.google.android.play.core.splitinstall.SplitInstallManager
-dontwarn com.google.android.play.core.splitinstall.SplitInstallManagerFactory
-dontwarn com.google.android.play.core.splitinstall.SplitInstallRequest$Builder
-dontwarn com.google.android.play.core.splitinstall.SplitInstallRequest
-dontwarn com.google.android.play.core.splitinstall.SplitInstallSessionState
-dontwarn com.google.android.play.core.splitinstall.SplitInstallStateUpdatedListener
-dontwarn com.google.android.play.core.tasks.OnFailureListener
-dontwarn com.google.android.play.core.tasks.OnSuccessListener
-dontwarn com.google.android.play.core.tasks.Task

# XML parser stuff
-dontwarn org.xmlpull.v1.**
-dontwarn org.kxml2.io.**
-dontwarn android.content.res.**
-dontwarn org.slf4j.impl.StaticLoggerBinder


-keep class org.xmlpull.** { *; }
-keepclassmembers class org.xmlpull.** { *; }

#Flutter Wrapper
-keep class io.flutter.app.** { *; }
-keep class io.flutter.plugin.** { *; }
Expand All @@ -6,6 +29,10 @@
-keep class io.flutter.** { *; }
-keep class io.flutter.plugins.** { *; }

# For Awesome Notification Plugin
-keep class com.google.common.reflect.TypeToken
-keep class * extends com.google.common.reflect.TypeToken

# You might not be using firebase
-keep class com.google.firebase.** { *; }
-keep class com.builttoroam.devicecalendar.** { *; }
Expand Down
1 change: 1 addition & 0 deletions app/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@

<!-- Add android:stopWithTask option only when necessary. -->
<application
android:name=".MyApp"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
Expand Down
11 changes: 11 additions & 0 deletions app/android/app/src/main/java/com/friend/ios/MyApp.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.friend.ios

import android.app.Application
import io.maido.intercom.IntercomFlutterPlugin

class MyApp : Application() {
override fun onCreate() {
super.onCreate()
IntercomFlutterPlugin.initSdk(this, appId = BuildConfig.INTERCOM_APP_ID, androidApiKey = BuildConfig.INTERCOM_ANDROID_API_KEY)
}
}
12 changes: 12 additions & 0 deletions app/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@ allprojects {
google()
mavenCentral()
}
subprojects {
afterEvaluate { project ->
if (project.hasProperty('android')) {
project.android {
if (namespace == null) {
namespace project.group
}
}
}
}
}
}

rootProject.buildDir = '../build'
Expand All @@ -13,6 +24,7 @@ subprojects {
project.evaluationDependsOn(':app')
}


tasks.register("clean", Delete) {
delete rootProject.buildDir
}
4 changes: 2 additions & 2 deletions app/android/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Fri Jun 23 08:50:38 CEST 2017
#Sun Sep 22 21:12:01 IST 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.4-bin.zip
4 changes: 2 additions & 2 deletions app/android/settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ pluginManagement {

plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "7.4.2" apply false
id "com.android.application" version "8.1.4" apply false
// START: FlutterFire Configuration
id "com.google.gms.google-services" version "4.3.15" apply false
// END: FlutterFire Configuration
id "org.jetbrains.kotlin.android" version "1.8.21" apply false
id "org.jetbrains.kotlin.android" version "1.9.21" apply false


}
Expand Down
2 changes: 1 addition & 1 deletion app/ios/Podfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
platform :ios, '14.0'
platform :ios, '15.0'

# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
Expand Down
18 changes: 9 additions & 9 deletions app/ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@
CODE_SIGN_ENTITLEMENTS = "Runner/RunnerDebug-prod.entitlements";
DEVELOPMENT_TEAM = 9536L8KLMP;
INFOPLIST_KEY_CFBundleDisplayName = Omi;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.friend-app-with-wearable.ios12";
PRODUCT_NAME = Runner;
TARGETED_DEVICE_FAMILY = 1;
Expand All @@ -461,7 +461,7 @@
CODE_SIGN_ENTITLEMENTS = "Runner/RunnerProfile-prod.entitlements";
DEVELOPMENT_TEAM = 9536L8KLMP;
INFOPLIST_KEY_CFBundleDisplayName = Omi;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.friend-app-with-wearable.ios12";
PRODUCT_NAME = Runner;
TARGETED_DEVICE_FAMILY = 1;
Expand All @@ -477,7 +477,7 @@
CODE_SIGN_ENTITLEMENTS = "Runner/RunnerRelease-prod.entitlements";
DEVELOPMENT_TEAM = 9536L8KLMP;
INFOPLIST_KEY_CFBundleDisplayName = Omi;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.friend-app-with-wearable.ios12";
PRODUCT_NAME = Runner;
TARGETED_DEVICE_FAMILY = 1;
Expand All @@ -493,7 +493,7 @@
CODE_SIGN_ENTITLEMENTS = "Runner/RunnerDebug-dev.entitlements";
DEVELOPMENT_TEAM = 9536L8KLMP;
INFOPLIST_KEY_CFBundleDisplayName = Omi;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.friend-app-with-wearable.ios12.development";
PRODUCT_NAME = Runner;
TARGETED_DEVICE_FAMILY = 1;
Expand All @@ -509,7 +509,7 @@
CODE_SIGN_ENTITLEMENTS = "Runner/RunnerProfile-dev.entitlements";
DEVELOPMENT_TEAM = 9536L8KLMP;
INFOPLIST_KEY_CFBundleDisplayName = Omi;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.friend-app-with-wearable.ios12.development";
PRODUCT_NAME = Runner;
TARGETED_DEVICE_FAMILY = 1;
Expand All @@ -525,7 +525,7 @@
CODE_SIGN_ENTITLEMENTS = "Runner/RunnerRelease-dev.entitlements";
DEVELOPMENT_TEAM = 9536L8KLMP;
INFOPLIST_KEY_CFBundleDisplayName = Omi;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.friend-app-with-wearable.ios12.development";
PRODUCT_NAME = Runner;
TARGETED_DEVICE_FAMILY = 1;
Expand Down Expand Up @@ -604,7 +604,7 @@
);
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Omi;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand Down Expand Up @@ -904,7 +904,7 @@
);
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Omi;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand Down Expand Up @@ -949,7 +949,7 @@
);
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Omi;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand Down
2 changes: 2 additions & 0 deletions app/ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@
<string>We need access to your photo library to allow you to upload and share photos through Instabug.</string>
<key>PermissionGroupNotification</key>
<string>You need to enable notifications to receive your pro-active feedback.</string>
<key>NSCameraUsageDescription</key>
<string>Camera access is required to report issues</string>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UIBackgroundModes</key>
Expand Down
12 changes: 12 additions & 0 deletions app/lib/env/dev_env.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,16 @@ final class DevEnv implements EnvFields {
@override
@EnviedField(varName: 'GLEAP_API_KEY', obfuscate: true)
final String? gleapApiKey = _DevEnv.gleapApiKey;

@override
@EnviedField(varName: 'INTERCOM_APP_ID', obfuscate: true)
final String? intercomAppId = _DevEnv.intercomAppId;

@override
@EnviedField(varName: 'INTERCOM_IOS_API_KEY', obfuscate: true)
final String? intercomIOSApiKey = _DevEnv.intercomIOSApiKey;

@override
@EnviedField(varName: 'INTERCOM_ANDROID_API_KEY', obfuscate: true)
final String? intercomAndroidApiKey = _DevEnv.intercomAndroidApiKey;
}
12 changes: 12 additions & 0 deletions app/lib/env/env.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ abstract class Env {
static String? get googleMapsApiKey => _instance.googleMapsApiKey;

static String? get gleapApiKey => _instance.gleapApiKey;

static String? get intercomAppId => _instance.intercomAppId;

static String? get intercomIOSApiKey => _instance.intercomIOSApiKey;

static String? get intercomAndroidApiKey => _instance.intercomAndroidApiKey;
}

abstract class EnvFields {
Expand All @@ -40,4 +46,10 @@ abstract class EnvFields {
String? get googleMapsApiKey;

String? get gleapApiKey;

String? get intercomAppId;

String? get intercomIOSApiKey;

String? get intercomAndroidApiKey;
}
12 changes: 12 additions & 0 deletions app/lib/env/prod_env.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,16 @@ final class ProdEnv implements EnvFields {
@override
@EnviedField(varName: 'GLEAP_API_KEY', obfuscate: true)
final String? gleapApiKey = _ProdEnv.gleapApiKey;

@override
@EnviedField(varName: 'INTERCOM_APP_ID', obfuscate: true)
final String? intercomAppId = _ProdEnv.intercomAppId;

@override
@EnviedField(varName: 'INTERCOM_IOS_API_KEY', obfuscate: true)
final String? intercomIOSApiKey = _ProdEnv.intercomIOSApiKey;

@override
@EnviedField(varName: 'INTERCOM_ANDROID_API_KEY', obfuscate: true)
final String? intercomAndroidApiKey = _ProdEnv.intercomAndroidApiKey;
}
17 changes: 15 additions & 2 deletions app/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import 'package:friend_private/providers/message_provider.dart';
import 'package:friend_private/providers/onboarding_provider.dart';
import 'package:friend_private/providers/plugin_provider.dart';
import 'package:friend_private/providers/speech_profile_provider.dart';
import 'package:friend_private/providers/websocket_provider.dart';
import 'package:friend_private/services/notification_service.dart';
import 'package:friend_private/services/services.dart';
import 'package:friend_private/utils/analytics/gleap.dart';
Expand All @@ -39,6 +38,7 @@ import 'package:friend_private/utils/features/calendar.dart';
import 'package:friend_private/utils/logger.dart';
import 'package:gleap_sdk/gleap_sdk.dart';
import 'package:instabug_flutter/instabug_flutter.dart';
import 'package:intercom_flutter/intercom_flutter.dart';
import 'package:opus_dart/opus_dart.dart';
import 'package:opus_flutter/opus_flutter.dart' as opus_flutter;
import 'package:provider/provider.dart';
Expand All @@ -58,6 +58,13 @@ Future<bool> _init() async {
await Firebase.initializeApp(options: dev.DefaultFirebaseOptions.currentPlatform, name: 'dev');
}

if (Env.intercomAppId != null) {
await Intercom.instance.initialize(
Env.intercomAppId!,
iosApiKey: Env.intercomIOSApiKey,
androidApiKey: Env.intercomAndroidApiKey,
);
}
await NotificationService.instance.initialize();
await SharedPreferencesUtil.init();
await MixpanelManager.init();
Expand Down Expand Up @@ -270,14 +277,20 @@ class DeciderWidget extends StatefulWidget {
class _DeciderWidgetState extends State<DeciderWidget> {
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) {
WidgetsBinding.instance.addPostFrameCallback((_) async {
if (context.read<ConnectivityProvider>().isConnected) {
NotificationService.instance.saveNotificationToken();
}

if (context.read<AuthenticationProvider>().user != null) {
context.read<HomeProvider>().setupHasSpeakerProfile();
await Intercom.instance.loginIdentifiedUser(
userId: FirebaseAuth.instance.currentUser!.uid,
);
context.read<MessageProvider>().setMessagesFromCache();
context.read<MessageProvider>().refreshMessages();
} else {
await Intercom.instance.loginUnidentifiedUser();
}
});
super.initState();
Expand Down
6 changes: 2 additions & 4 deletions app/lib/pages/capture/connect.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:friend_private/pages/home/device_settings.dart';
import 'package:friend_private/pages/settings/device_settings.dart';
import 'package:friend_private/pages/home/page.dart';
import 'package:friend_private/pages/onboarding/find_device/page.dart';
import 'package:friend_private/utils/other/temp.dart';
Expand All @@ -24,9 +24,7 @@ class _ConnectDevicePageState extends State<ConnectDevicePage> {
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const DeviceSettings(
isDeviceConnected: false,
),
builder: (context) => const DeviceSettings(),
),
);
},
Expand Down
Loading

0 comments on commit f01db3f

Please sign in to comment.