Merge pull request #2 from GetStream/fix/loading-screen
feat: Added native and local splash screens
@@ -2,6 +2,7 @@
|
||||
.atom/
|
||||
.idea/
|
||||
.vscode/
|
||||
**/.fvm/
|
||||
|
||||
.packages
|
||||
.pub/
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Modify this file to customize your launch splash screen -->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@android:color/white" />
|
||||
|
||||
<!-- You can insert your own image assets here -->
|
||||
<!-- <item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@mipmap/launch_image" />
|
||||
</item> -->
|
||||
<item android:drawable="@color/splash_color"/>
|
||||
</layer-list>
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="splash_color">#005fff</color>
|
||||
</resources>
|
||||
@@ -1 +1 @@
|
||||
15590bfc713ca5ccd71d79a75eb28980
|
||||
c3757524e06ced55f3d1b83411b9e99c
|
||||
@@ -1,2 +1,3 @@
|
||||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||
#include "Generated.xcconfig"
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||
#include "Generated.xcconfig"
|
||||
|
||||
@@ -309,10 +309,11 @@
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
|
||||
"${BUILT_PRODUCTS_DIR}/Starscream-framework/Starscream.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/StreamChatClient-framework/StreamChatClient.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/DKImagePickerController/DKImagePickerController.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/DKPhotoGallery/DKPhotoGallery.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/FMDB/FMDB.framework",
|
||||
"${PODS_ROOT}/../Flutter/Flutter.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/SDWebImage/SDWebImage.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/SwiftyGif/SwiftyGif.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/esys_flutter_share/esys_flutter_share.framework",
|
||||
@@ -336,10 +337,11 @@
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Starscream.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/StreamChatClient.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DKImagePickerController.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DKPhotoGallery.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FMDB.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImage.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftyGif.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/esys_flutter_share.framework",
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:Runner.xcodeproj">
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "background.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 70 B |
@@ -1,23 +1,23 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "LaunchImage.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "LaunchImage@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "LaunchImage@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 68 B |
|
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 68 B |
|
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 68 B |
@@ -16,13 +16,19 @@
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<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">
|
||||
</imageView>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" image="LaunchBackground" translatesAutoresizingMaskIntoConstraints="NO" id="tWc-Dq-wcI"/>
|
||||
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4"></imageView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<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"/>
|
||||
<constraint firstItem="YRO-k0-Ey4" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" id="3T2-ad-Qdv"/>
|
||||
<constraint firstItem="tWc-Dq-wcI" firstAttribute="bottom" secondItem="Ze5-6b-2t3" secondAttribute="bottom" id="RPx-PI-7Xg"/>
|
||||
<constraint firstItem="tWc-Dq-wcI" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="SdS-ul-q2q"/>
|
||||
<constraint firstAttribute="trailing" secondItem="tWc-Dq-wcI" secondAttribute="trailing" id="Swv-Gf-Rwn"/>
|
||||
<constraint firstAttribute="trailing" secondItem="YRO-k0-Ey4" secondAttribute="trailing" id="TQA-XW-tRk"/>
|
||||
<constraint firstItem="YRO-k0-Ey4" firstAttribute="bottom" secondItem="Ze5-6b-2t3" secondAttribute="bottom" id="duK-uY-Gun"/>
|
||||
<constraint firstItem="tWc-Dq-wcI" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" id="kV7-tw-vXt"/>
|
||||
<constraint firstItem="YRO-k0-Ey4" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="xPn-NY-SIU"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</viewController>
|
||||
@@ -33,5 +39,6 @@
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="LaunchImage" width="168" height="185"/>
|
||||
<image name="LaunchBackground" width="1" height="1"/>
|
||||
</resources>
|
||||
</document>
|
||||
</document>
|
||||
@@ -1,64 +1,66 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>ChatSample</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSAppleMusicUsageDescription</key>
|
||||
<string>Used to send message attachments</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Used to send message attachments</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>Used to send message attachments</string>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>Used to send message attachments</string>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>fetch</string>
|
||||
<string>remote-notification</string>
|
||||
</array>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<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>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>remote-notification</string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>ChatSample</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSAppleMusicUsageDescription</key>
|
||||
<string>Used to send message attachments</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Used to send message attachments</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>Used to send message attachments</string>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>Used to send message attachments</string>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>fetch</string>
|
||||
<string>remote-notification</string>
|
||||
</array>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<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>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>remote-notification</string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<true/>
|
||||
<key>UIStatusBarHidden</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -33,7 +33,6 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow,
|
||||
resizeToAvoidBottomPadding: false,
|
||||
appBar: AppBar(
|
||||
backgroundColor: StreamChatTheme.of(context).colorTheme.white,
|
||||
elevation: 1,
|
||||
|
||||
@@ -6,8 +6,10 @@ import 'package:example/group_info_screen.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/scheduler.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:lottie/lottie.dart';
|
||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||
import 'package:stream_chat_persistence/stream_chat_persistence.dart';
|
||||
import 'package:streaming_shared_preferences/streaming_shared_preferences.dart';
|
||||
@@ -18,86 +20,237 @@ import 'routes/routes.dart';
|
||||
import 'search_text_field.dart';
|
||||
|
||||
final chatPersistentClient = StreamChatPersistenceClient(
|
||||
logLevel: Level.INFO,
|
||||
logLevel: Level.SEVERE,
|
||||
connectionMode: ConnectionMode.background,
|
||||
);
|
||||
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
final secureStorage = FlutterSecureStorage();
|
||||
|
||||
final apiKey = await secureStorage.read(key: kStreamApiKey);
|
||||
final userId = await secureStorage.read(key: kStreamUserId);
|
||||
|
||||
final client = StreamChatClient(
|
||||
apiKey ?? kDefaultStreamApiKey,
|
||||
logLevel: Level.INFO,
|
||||
)..chatPersistenceClient = chatPersistentClient;
|
||||
|
||||
if (userId != null) {
|
||||
final token = await secureStorage.read(key: kStreamToken);
|
||||
await client.connectUser(
|
||||
User(id: userId),
|
||||
token,
|
||||
);
|
||||
}
|
||||
|
||||
runApp(MyApp(client));
|
||||
runApp(MyApp());
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
final StreamChatClient client;
|
||||
class MyApp extends StatefulWidget {
|
||||
@override
|
||||
_MyAppState createState() => _MyAppState();
|
||||
}
|
||||
|
||||
MyApp(this.client);
|
||||
class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
|
||||
InitData _initData;
|
||||
bool _animCompleted = false;
|
||||
Animation<double> _animation, _scaleAnimation;
|
||||
AnimationController _animationController, _scaleAnimationController;
|
||||
Animation<Color> _colorAnimation;
|
||||
int timeOfStartMs;
|
||||
|
||||
Future<InitData> _initConnection() async {
|
||||
final secureStorage = FlutterSecureStorage();
|
||||
|
||||
final apiKey = await secureStorage.read(key: kStreamApiKey);
|
||||
final userId = await secureStorage.read(key: kStreamUserId);
|
||||
|
||||
final client = StreamChatClient(
|
||||
apiKey ?? kDefaultStreamApiKey,
|
||||
logLevel: Level.SEVERE,
|
||||
)..chatPersistenceClient = chatPersistentClient;
|
||||
|
||||
if (userId != null) {
|
||||
final token = await secureStorage.read(key: kStreamToken);
|
||||
await client.connectUser(
|
||||
User(id: userId),
|
||||
token,
|
||||
);
|
||||
}
|
||||
|
||||
var prefs = await StreamingSharedPreferences.instance;
|
||||
|
||||
return InitData(client, prefs);
|
||||
}
|
||||
|
||||
void _createAnimations() {
|
||||
_scaleAnimationController = AnimationController(
|
||||
vsync: this,
|
||||
value: 0,
|
||||
duration: Duration(
|
||||
milliseconds: 500,
|
||||
),
|
||||
);
|
||||
_scaleAnimation = Tween(
|
||||
begin: 1.0,
|
||||
end: 1.5,
|
||||
).animate(CurvedAnimation(
|
||||
parent: _scaleAnimationController,
|
||||
curve: Curves.easeInOutBack,
|
||||
));
|
||||
|
||||
_animationController = AnimationController(
|
||||
vsync: this,
|
||||
duration: Duration(
|
||||
milliseconds: 1000,
|
||||
),
|
||||
);
|
||||
_animation = Tween(
|
||||
begin: 0.0,
|
||||
end: 1000.0,
|
||||
).animate(CurvedAnimation(
|
||||
parent: _animationController,
|
||||
curve: Curves.easeInOut,
|
||||
));
|
||||
_colorAnimation = ColorTween(
|
||||
begin: Color(0xff005FFF),
|
||||
end: Color(0xff005FFF),
|
||||
).animate(CurvedAnimation(
|
||||
parent: _animationController,
|
||||
curve: Curves.easeInOut,
|
||||
));
|
||||
_colorAnimation = ColorTween(
|
||||
begin: Color(0xff005FFF),
|
||||
end: Colors.transparent,
|
||||
).animate(CurvedAnimation(
|
||||
parent: _animationController,
|
||||
curve: Curves.easeInOut,
|
||||
));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FutureBuilder<StreamingSharedPreferences>(
|
||||
future: StreamingSharedPreferences.instance,
|
||||
builder: (context, snapshot) {
|
||||
if (!snapshot.hasData) {
|
||||
return SizedBox();
|
||||
void initState() {
|
||||
timeOfStartMs = DateTime.now().millisecondsSinceEpoch;
|
||||
|
||||
_createAnimations();
|
||||
|
||||
_initConnection().then(
|
||||
(initData) {
|
||||
setState(() {
|
||||
_initData = initData;
|
||||
});
|
||||
|
||||
var now = DateTime.now().millisecondsSinceEpoch;
|
||||
|
||||
if (now - timeOfStartMs > 1500) {
|
||||
SchedulerBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
_scaleAnimationController.forward().whenComplete(() {
|
||||
_animationController.forward();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
Future.delayed(Duration(milliseconds: 1500)).then((value) {
|
||||
_scaleAnimationController.forward().whenComplete(() {
|
||||
_animationController.forward();
|
||||
});
|
||||
});
|
||||
}
|
||||
return PreferenceBuilder<int>(
|
||||
preference: snapshot.data.getInt(
|
||||
'theme',
|
||||
defaultValue: 0,
|
||||
},
|
||||
);
|
||||
_animationController.addStatusListener((status) {
|
||||
if (status == AnimationStatus.completed) {
|
||||
setState(() {
|
||||
_animCompleted = true;
|
||||
});
|
||||
}
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
Widget _buildAnimation() {
|
||||
return MaterialApp(
|
||||
home: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
AnimatedBuilder(
|
||||
animation: _scaleAnimation,
|
||||
builder: (context, _) {
|
||||
return Transform.scale(
|
||||
scale: _scaleAnimation.value,
|
||||
child: AnimatedBuilder(
|
||||
animation: _colorAnimation,
|
||||
builder: (context, snapshot) {
|
||||
return Container(
|
||||
alignment: Alignment.center,
|
||||
constraints: BoxConstraints.expand(),
|
||||
color: _colorAnimation == null
|
||||
? Color(0xff005FFF)
|
||||
: _colorAnimation.value,
|
||||
child: !_animationController.isAnimating
|
||||
? Lottie.asset(
|
||||
'assets/floating_boat.json',
|
||||
alignment: Alignment.center,
|
||||
)
|
||||
: SizedBox(),
|
||||
);
|
||||
}),
|
||||
);
|
||||
},
|
||||
),
|
||||
builder: (context, snapshot) => MaterialApp(
|
||||
builder: (context, child) {
|
||||
return StreamChat(
|
||||
client: client,
|
||||
onBackgroundEventReceived: (e) =>
|
||||
showLocalNotification(e, client.state.user.id),
|
||||
child: Builder(
|
||||
builder: (context) => AnnotatedRegion<SystemUiOverlayStyle>(
|
||||
child: child,
|
||||
value: SystemUiOverlayStyle(
|
||||
systemNavigationBarColor:
|
||||
StreamChatTheme.of(context).colorTheme.white,
|
||||
systemNavigationBarIconBrightness:
|
||||
Theme.of(context).brightness == Brightness.dark
|
||||
? Brightness.light
|
||||
: Brightness.dark,
|
||||
),
|
||||
AnimatedBuilder(
|
||||
animation: _animation,
|
||||
builder: (context, snapshot) {
|
||||
return Transform.scale(
|
||||
scale: _animation.value,
|
||||
child: Container(
|
||||
width: 1.0,
|
||||
height: 1.0,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white
|
||||
.withOpacity(1 - _animationController.value),
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
debugShowCheckedModeBanner: false,
|
||||
theme: ThemeData.light(),
|
||||
darkTheme: ThemeData.dark(),
|
||||
themeMode: {
|
||||
-1: ThemeMode.dark,
|
||||
0: ThemeMode.system,
|
||||
1: ThemeMode.light,
|
||||
}[snapshot],
|
||||
onGenerateRoute: AppRoutes.generateRoute,
|
||||
initialRoute:
|
||||
client.state.user == null ? Routes.CHOOSE_USER : Routes.HOME,
|
||||
),
|
||||
);
|
||||
},
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
if (_initData != null)
|
||||
PreferenceBuilder<int>(
|
||||
preference: _initData.preferences.getInt(
|
||||
'theme',
|
||||
defaultValue: 0,
|
||||
),
|
||||
builder: (context, snapshot) => MaterialApp(
|
||||
builder: (context, child) {
|
||||
return StreamChat(
|
||||
client: _initData.client,
|
||||
onBackgroundEventReceived: (e) =>
|
||||
showLocalNotification(e, _initData.client.state.user.id),
|
||||
child: Builder(
|
||||
builder: (context) => AnnotatedRegion<SystemUiOverlayStyle>(
|
||||
child: child,
|
||||
value: SystemUiOverlayStyle(
|
||||
systemNavigationBarColor:
|
||||
StreamChatTheme.of(context).colorTheme.white,
|
||||
systemNavigationBarIconBrightness:
|
||||
Theme.of(context).brightness == Brightness.dark
|
||||
? Brightness.light
|
||||
: Brightness.dark,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
theme: ThemeData.light(),
|
||||
darkTheme: ThemeData.dark(),
|
||||
themeMode: {
|
||||
-1: ThemeMode.dark,
|
||||
0: ThemeMode.system,
|
||||
1: ThemeMode.light,
|
||||
}[snapshot],
|
||||
onGenerateRoute: AppRoutes.generateRoute,
|
||||
initialRoute: _initData.client.state.user == null
|
||||
? Routes.CHOOSE_USER
|
||||
: Routes.HOME,
|
||||
),
|
||||
),
|
||||
if (!_animCompleted) _buildAnimation(),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -833,3 +986,57 @@ class _ThreadPageState extends State<ThreadPage> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class InitData {
|
||||
final StreamChatClient client;
|
||||
final StreamingSharedPreferences preferences;
|
||||
|
||||
InitData(this.client, this.preferences);
|
||||
}
|
||||
|
||||
class HolePainter extends CustomPainter {
|
||||
HolePainter({
|
||||
@required this.color,
|
||||
@required this.holeSize,
|
||||
});
|
||||
|
||||
Color color;
|
||||
double holeSize;
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
double radius = holeSize / 2;
|
||||
Rect rect = Rect.fromLTWH(0, 0, size.width, size.height);
|
||||
Rect outerCircleRect = Rect.fromCircle(
|
||||
center: Offset(size.width / 2, size.height / 2), radius: radius);
|
||||
Rect innerCircleRect = Rect.fromCircle(
|
||||
center: Offset(size.width / 2, size.height / 2), radius: radius / 2);
|
||||
|
||||
Path transparentHole = Path.combine(
|
||||
PathOperation.difference,
|
||||
Path()..addRect(rect),
|
||||
Path()
|
||||
..addOval(outerCircleRect)
|
||||
..close(),
|
||||
);
|
||||
|
||||
Path halfTransparentRing = Path.combine(
|
||||
PathOperation.difference,
|
||||
Path()
|
||||
..addOval(outerCircleRect)
|
||||
..close(),
|
||||
Path()
|
||||
..addOval(innerCircleRect)
|
||||
..close(),
|
||||
);
|
||||
|
||||
canvas.drawPath(transparentHole, Paint()..color = color);
|
||||
canvas.drawPath(
|
||||
halfTransparentRing, Paint()..color = color.withOpacity(0.5));
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(CustomPainter oldDelegate) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ class AppRoutes {
|
||||
return MaterialPageRoute(
|
||||
settings: const RouteSettings(name: Routes.APP),
|
||||
builder: (_) {
|
||||
return MyApp(args);
|
||||
return MyApp();
|
||||
});
|
||||
case Routes.HOME:
|
||||
return MaterialPageRoute(
|
||||
|
||||
@@ -17,12 +17,9 @@ dependencies:
|
||||
yaml: ^2.2.1
|
||||
uuid: ^2.2.2
|
||||
streaming_shared_preferences: ^1.0.2
|
||||
lottie: ^0.7.0+1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_driver:
|
||||
sdk: flutter
|
||||
flutter_launcher_icons: ^0.8.1
|
||||
test: any
|
||||
|
||||
|
||||