diff --git a/assets/icons/facebook.svg b/assets/icons/facebook.svg new file mode 100644 index 0000000..e4568d5 --- /dev/null +++ b/assets/icons/facebook.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/assets/icons/google.svg b/assets/icons/google.svg new file mode 100644 index 0000000..74fd07b --- /dev/null +++ b/assets/icons/google.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/icons/qrr.png b/assets/icons/qrr.png new file mode 100644 index 0000000..52c2cb5 Binary files /dev/null and b/assets/icons/qrr.png differ diff --git a/assets/icons/s1.png b/assets/icons/s1.png new file mode 100644 index 0000000..2e6cc31 Binary files /dev/null and b/assets/icons/s1.png differ diff --git a/assets/icons/s2.png b/assets/icons/s2.png new file mode 100644 index 0000000..9bd7769 Binary files /dev/null and b/assets/icons/s2.png differ diff --git a/assets/icons/s3.png b/assets/icons/s3.png new file mode 100644 index 0000000..c1f33cc Binary files /dev/null and b/assets/icons/s3.png differ diff --git a/assets/icons/s4.png b/assets/icons/s4.png new file mode 100644 index 0000000..ad345e1 Binary files /dev/null and b/assets/icons/s4.png differ diff --git a/assets/icons/s5.png b/assets/icons/s5.png new file mode 100644 index 0000000..4491721 Binary files /dev/null and b/assets/icons/s5.png differ diff --git a/assets/icons/slider_test.dart b/assets/icons/slider_test.dart new file mode 100644 index 0000000..390d43c --- /dev/null +++ b/assets/icons/slider_test.dart @@ -0,0 +1,692 @@ +import 'dart:async'; +import 'dart:math'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +class OnBoardingSlider extends StatefulWidget { + const OnBoardingSlider({Key? key}) : super(key: key); + + @override + State createState() => _OnBoardingSliderState(); +} + +class _OnBoardingSliderState extends State { + final PageController _pageController = PageController(); + int _currentPage = 0; + + @override + var imageList = [ + 'assets/s1.png', + 'assets/s2.png', + 'assets/s3.png', + 'assets/s4.png', + 'assets/s5.png' + ]; + + int currentIndex = 0; + + Widget buildDot(int index) { + return Container( + margin: EdgeInsets.all(5), + width: 10, + height: 10, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: currentIndex == index ? Colors.white : Colors.grey, + ), + ); + } + + Widget buildGallery3D() { + return Gallery3D( + controller: Gallery3DController( + itemCount: imageList.length, + ellipseHeight: 0, + autoLoop: true, + minScale: 0.4, + delayTime: 2000, + scrollTime: 1000, + ), + width: MediaQuery.of(context).size.width, + height: 300, + isClip: true, + onItemChanged: (index) { + setState( + () { + currentIndex = index; + _currentPage = index; + }, + ); + }, + itemConfig: const GalleryItemConfig( + width: 180, + height: 850, + radius: 10, + isShowTransformMask: false, + ), + onClickItem: (index) { + if (kDebugMode) print("currentIndex:$index"); + }, + itemBuilder: (context, index) { + return Image.asset( + imageList[index], + fit: BoxFit.fill, + ); + }, + ); + } + + @override + Widget build(BuildContext context) { + var screenHeight = MediaQuery.of(context).size.height; + + return Expanded( + child: Column( + children: [ + // Expanded( + // child: + Container( + height: screenHeight / 4, + child: PageView.builder( + controller: _pageController, + itemCount: imageList.length, + itemBuilder: ((context, index) { + return buildGallery3D(); + }), + onPageChanged: (index) { + setState(() { + _currentPage = index; + }); + }, + ), + // ), + ), + SizedBox(height: 16), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: List.generate( + imageList.length, + (index) => buildDot(index), + ), + ), + ], + ), + ); + } +} + +class Gallery3D extends StatefulWidget { + final double? height; + final double width; + final IndexedWidgetBuilder itemBuilder; + final ValueChanged? onItemChanged; + final ValueChanged? onClickItem; + final Gallery3DController controller; + final GalleryItemConfig itemConfig; + final EdgeInsetsGeometry? padding; + final bool isClip; + + Gallery3D( + {Key? key, + this.onClickItem, + this.onItemChanged, + this.isClip = true, + this.height, + this.padding, + required this.itemConfig, + required this.controller, + required this.width, + required this.itemBuilder}) + : super(key: key); + + @override + _Gallery3DState createState() => _Gallery3DState(); +} + +class _Gallery3DState extends State + with TickerProviderStateMixin, WidgetsBindingObserver, Gallery3DMixin { + List _galleryItemWidgetList = []; + AnimationController? _autoScrollAnimationController; + Timer? _timer; + + late Gallery3DController controller = widget.controller; + + AppLifecycleState appLifecycleState = AppLifecycleState.resumed; + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + appLifecycleState = state; + super.didChangeAppLifecycleState(state); + } + + @override + void initState() { + controller.widgetWidth = widget.width; + controller.vsync = this; + controller.init(widget.itemConfig); + + _updateWidgetIndexOnStack(); + if (controller.autoLoop) { + this._timer = + Timer.periodic(Duration(milliseconds: controller.delayTime), (timer) { + if (!mounted) return; + if (appLifecycleState != AppLifecycleState.resumed) return; + if (DateTime.now().millisecondsSinceEpoch - _lastTouchMillisecond < + controller.delayTime) return; + if (_isTouching) return; + animateTo(controller.getOffsetAngleFormTargetIndex( + getNextIndex(controller.currentIndex))); + }); + } + + WidgetsBinding.instance.addObserver(this); + + super.initState(); + } + + @override + void dispose() { + WidgetsBinding.instance.removeObserver(this); + _timer?.cancel(); + _timer = null; + _autoScrollAnimationController?.stop(canceled: true); + super.dispose(); + } + + @override + void animateTo(angle) { + _isTouching = true; + _lastTouchMillisecond = DateTime.now().millisecondsSinceEpoch; + _scrollToAngle(angle); + } + + @override + void jumpTo(angle) { + setState(() { + _updateAllGalleryItemTransformByAngle(angle); + }); + } + + var _isTouching = false; + var _lastTouchMillisecond = 0; + Offset? _panDownLocation; + Offset? _lastUpdateLocation; + + @override + Widget build(BuildContext context) { + return Container( + width: widget.width, + height: widget.height ?? widget.itemConfig.height, + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onHorizontalDragCancel: (() { + _onFingerUp(); + }), + onHorizontalDragDown: (details) { + _isTouching = true; + _panDownLocation = details.localPosition; + _lastUpdateLocation = details.localPosition; + _lastTouchMillisecond = DateTime.now().millisecondsSinceEpoch; + }, + onHorizontalDragEnd: (details) { + _onFingerUp(); + }, + onHorizontalDragStart: (details) {}, + onHorizontalDragUpdate: (details) { + setState(() { + _lastUpdateLocation = details.localPosition; + _lastTouchMillisecond = DateTime.now().millisecondsSinceEpoch; + _updateAllGalleryItemTransformByOffsetDx(details.delta.dx); + }); + }, + child: _buildWidgetList(), + ), + ); + } + + Widget _buildWidgetList() { + if (widget.isClip) { + return ClipRect( + child: Stack( + children: _galleryItemWidgetList, + )); + } + return Stack( + children: _galleryItemWidgetList, + ); + } + + void _scrollToAngle(double angle) { + _autoScrollAnimationController = + AnimationController(duration: Duration(milliseconds: 100), vsync: this); + + Animation animation; + + if (angle.ceil().abs() == 0) return; + animation = + Tween(begin: 0.0, end: angle).animate(_autoScrollAnimationController!); + + double lastValue = 0; + animation.addListener(() { + setState(() { + _updateAllGalleryItemTransformByAngle(animation.value - lastValue); + lastValue = animation.value; + }); + }); + _autoScrollAnimationController?.forward(); + _autoScrollAnimationController?.addListener(() { + if (_autoScrollAnimationController != null && + _autoScrollAnimationController!.isCompleted) { + _isTouching = false; + } + }); + } + + void _onFingerUp() { + if (_lastUpdateLocation == null) { + _isTouching = false; + return; + } + + double angle = controller.getTransformInfo(controller.currentIndex).angle; + double targetAngle = 0; + + var offsetX = _lastUpdateLocation!.dx - _panDownLocation!.dx; + + // Adjust the threshold for considering it a swipe + double swipeThreshold = widget.width * 0.1; + + if (offsetX.abs() > swipeThreshold) { + // Swipe detected + if (offsetX > 0) { + // Swipe to the right, move to the bottom + targetAngle = controller + .getTransformInfo(getPreIndex(controller.currentIndex)) + .angle + + 180; // Move to the bottom + } else { + // Swipe to the left + targetAngle = angle + 180; // Maintain the current position + } + } else { + // No swipe, move to the bottom from the current position + targetAngle = angle + 180; // Move to the bottom + } + + _scrollToAngle(targetAngle); + } + + void _updateAllGalleryItemTransformByAngle(double angle) { + controller.updateTransformByAngle(angle); + _updateAllGalleryItemTransform(); + } + + void _updateAllGalleryItemTransformByOffsetDx(double offsetDx) { + controller.updateTransformByOffsetDx(offsetDx); + _updateAllGalleryItemTransform(); + } + + void _updateAllGalleryItemTransform() { + for (var i = 0; i < controller.getTransformInfoListSize(); i++) { + var item = controller.getTransformInfo(i); + + if (item.angle > 180 - controller.unitAngle / 2 && + item.angle < 180 + controller.unitAngle / 2) { + if (controller.currentIndex != i) { + controller.currentIndex = i; + widget.onItemChanged?.call(controller.currentIndex); + } + } + _updateWidgetIndexOnStack(); + } + } + + /// Get Pre Index >>> + int getPreIndex(int index) { + var preIndex = index - 1; + if (preIndex < 0) { + preIndex = controller.itemCount - 1; + } + return preIndex; + } + + /// Get Next Index >>> + int getNextIndex(int index) { + var nextIndex = index + 1; + if (nextIndex == controller.itemCount) { + nextIndex = 0; + } + return nextIndex; + } + + List _leftWidgetList = []; + List _rightWidgetList = []; + List _tempList = []; + + /// Update Widget Index >>> + void _updateWidgetIndexOnStack() { + _leftWidgetList.clear(); + _rightWidgetList.clear(); + _tempList.clear(); + + for (var i = 0; i < controller.getTransformInfoListSize(); i++) { + var angle = controller.getTransformInfo(i).angle; + + if (angle >= 180 + controller.unitAngle / 2) { + _leftWidgetList.add(_buildGalleryItem( + i, + )); + } else { + _rightWidgetList.add(_buildGalleryItem( + i, + )); + } + } + + _rightWidgetList.sort((widget1, widget2) => + widget1.transformInfo.angle.compareTo(widget2.transformInfo.angle)); + + _rightWidgetList.forEach((element) { + if (element.transformInfo.angle < controller.unitAngle / 2) { + element.transformInfo.angle += 360; + _tempList.add(element); + } + }); + + _tempList.forEach((element) { + _rightWidgetList.remove(element); + }); + + _leftWidgetList.sort((widget1, widget2) => + widget2.transformInfo.angle.compareTo(widget1.transformInfo.angle)); + + _galleryItemWidgetList = [ + ..._leftWidgetList, + ..._rightWidgetList, + ]; + } + + /// Build Gallery Item >>>>> + GalleryItem _buildGalleryItem(int index) { + return GalleryItem( + index: index, + ellipseHeight: controller.ellipseHeight, + builder: widget.itemBuilder, + config: widget.itemConfig, + onClick: (index) { + if (widget.onClickItem != null && index == controller.currentIndex) { + widget.onClickItem?.call(index); + } + }, + transformInfo: controller.getTransformInfo(index), + ); + } +} + +class _GalleryItemTransformInfo { + Offset offset; + double scale; + double angle; + int index; + + _GalleryItemTransformInfo( + {required this.index, + this.scale = 1, + this.angle = 0, + this.offset = Offset.zero}); +} + +class GalleryItem extends StatelessWidget { + final GalleryItemConfig config; + final double ellipseHeight; + final int index; + final IndexedWidgetBuilder builder; + final ValueChanged? onClick; + final _GalleryItemTransformInfo transformInfo; + + final double minScale; + GalleryItem({ + Key? key, + required this.index, + required this.transformInfo, + required this.config, + required this.builder, + this.minScale = 0.4, + this.onClick, + this.ellipseHeight = 0, + }) : super(key: key); + + Widget _buildItem(BuildContext context) { + return Container( + width: config.width, + height: config.height, + child: builder(context, index)); + } + + Widget _buildMaskTransformItem(Widget child) { + if (!config.isShowTransformMask) return child; + return Stack(children: [ + child, + Container( + width: config.width, + height: config.height, + color: Color.fromARGB( + 100 * (1 - transformInfo.scale) ~/ (1 - minScale), 0, 0, 0), + ) + ]); + } + + Widget _buildRadiusItem(Widget child) { + if (config.radius <= 0) return child; + return ClipRRect( + borderRadius: BorderRadius.circular(config.radius), child: child); + } + + Widget _buildShadowItem(Widget child) { + if (config.shadows.isEmpty) return child; + return Container( + child: child, decoration: BoxDecoration(boxShadow: config.shadows)); + } + + @override + Widget build(BuildContext context) { + return Transform.translate( + offset: transformInfo.offset, + child: Container( + width: config.width, + height: config.height, + child: Transform.scale( + scale: transformInfo.scale, + child: InkWell( + highlightColor: Colors.transparent, + splashColor: Colors.transparent, + onTap: () => onClick?.call(index), + child: _buildShadowItem( + _buildRadiusItem(_buildMaskTransformItem(_buildItem(context)))), + ), + ), + ), + ); + } +} + +/// Gallery Item Config >>>>> +class GalleryItemConfig { + final double width; + final double height; + final double radius; + final List shadows; + final bool isShowTransformMask; + + const GalleryItemConfig( + {this.width = 220, + this.height = 600, + this.radius = 0, + this.isShowTransformMask = true, + this.shadows = const []}); +} + +class Gallery3DController { + double perimeter = 0; + double unitAngle = 0; + final double minScale; + double widgetWidth = 0; + double ellipseHeight; + int itemCount; + late GalleryItemConfig itemConfig; + int currentIndex = 0; + final int delayTime; + final int scrollTime; + final bool autoLoop; + late Gallery3DMixin vsync; + List<_GalleryItemTransformInfo> _galleryItemTransformInfoList = []; + double baseAngleOffset = 0; + Gallery3DController( + {required this.itemCount, + this.ellipseHeight = 0, + this.autoLoop = true, + this.minScale = 0.4, + this.delayTime = 5000, + this.scrollTime = 1000}) + : assert(itemCount >= 3, 'ItemCount must be greater than or equal to 3'); + + void init(GalleryItemConfig itemConfig) { + this.itemConfig = itemConfig; + unitAngle = 360 / itemCount; + perimeter = calculatePerimeter(widgetWidth * 0.7, 50); + + _galleryItemTransformInfoList.clear(); + for (var i = 0; i < itemCount; i++) { + var itemAngle = getItemAngle(i); + _galleryItemTransformInfoList.add(_GalleryItemTransformInfo( + index: i, + angle: itemAngle, + scale: calculateScale(itemAngle), + offset: calculateOffset(itemAngle))); + } + } + + _GalleryItemTransformInfo getTransformInfo(int index) { + return _galleryItemTransformInfoList[index]; + } + + int getTransformInfoListSize() { + return _galleryItemTransformInfoList.length; + } + + double getItemAngle(int index) { + double angle = 360 - (index * unitAngle + 180) % 360; + return angle; + } + + void updateTransformByAngle(double offsetAngle) { + baseAngleOffset -= offsetAngle; + for (int index = 0; index < _galleryItemTransformInfoList.length; index++) { + _GalleryItemTransformInfo transformInfo = + _galleryItemTransformInfoList[index]; + + double angle = getItemAngle(index); + double scale = transformInfo.scale; + Offset offset = transformInfo.offset; + + if (baseAngleOffset.abs() > 360) { + baseAngleOffset %= 360; + } + + angle += baseAngleOffset; + angle = angle % 360; + + offset = calculateOffset(angle); + + scale = calculateScale(angle); + + transformInfo + ..angle = angle + ..scale = scale + ..offset = offset; + } + } + + void updateTransformByOffsetDx(double offsetDx) { + double offsetAngle = offsetDx / perimeter / 2 * 360; + updateTransformByAngle(offsetAngle); + } + + /// Calculate Scale >>>> + double calculateScale(double angle) { + angle = angle % 360; + if (angle > 180) { + angle = 360 - angle; + } + + angle += 30; + + var scale = angle / 180.0; + + if (scale > 1) { + scale = 1; + } else if (scale < minScale) { + scale = minScale; + } + + return scale; + } + + /// Calculate Offset >>>> + Offset calculateOffset(double angle) { + double width = widgetWidth * 1; + + double radiusOuterX = width / 2.4; + + double radiusOuterY = ellipseHeight; + + double angleOuter = (4 * pi / 360) * angle; + double x = radiusOuterX * sin(angleOuter); + double y = radiusOuterY > 0 ? radiusOuterY * cos(angleOuter) : 0; + + return Offset(x + (widgetWidth - itemConfig.width) / 2, -y); + } + + /// Calculate Perimeter >>>> + double calculatePerimeter(double width, double height) { + var a = width; + // var a = width * 0.8; + var b = height; + return 2 * pi * b + 4 * (a - b); + } + + /// Get Final Angle >>>> + double getFinalAngle(double angle) { + if (angle >= 360) { + angle -= 360; + } else if (angle < 0) { + angle += 360; + } + return angle; + } + + double getOffsetAngleFormTargetIndex(int index) { + double targetItemAngle = getItemAngle(index) + baseAngleOffset; + + double offsetAngle = targetItemAngle % 180; + if (targetItemAngle < 180 || targetItemAngle > 360) { + offsetAngle = offsetAngle - 180; + } + + return offsetAngle; + } + + void animateTo(int index) { + if (index == currentIndex) return; + vsync.animateTo(getOffsetAngleFormTargetIndex(index)); + } + + void jumpTo(int index) { + if (index == currentIndex) return; + vsync.jumpTo(getOffsetAngleFormTargetIndex(index)); + } +} + +mixin class Gallery3DMixin { + void animateTo(angle) {} + void jumpTo(angle) {} +} diff --git a/assets/icons/x.svg b/assets/icons/x.svg new file mode 100644 index 0000000..c11beeb --- /dev/null +++ b/assets/icons/x.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/ios/assets/fonts/SF Pro/SFProDisplay-Semibold.ttf b/ios/assets/fonts/SF Pro/SFProDisplay-Semibold.ttf new file mode 100644 index 0000000..00a92ac Binary files /dev/null and b/ios/assets/fonts/SF Pro/SFProDisplay-Semibold.ttf differ diff --git a/ios/assets/fonts/SF UI/sf-ui-text-regular.ttf b/ios/assets/fonts/SF UI/sf-ui-text-regular.ttf new file mode 100644 index 0000000..f31e7b3 Binary files /dev/null and b/ios/assets/fonts/SF UI/sf-ui-text-regular.ttf differ diff --git a/ios/assets/fonts/SourceHanSansCN-Bold.otf b/ios/assets/fonts/SourceHanSansCN-Bold.otf new file mode 100644 index 0000000..4b3429a Binary files /dev/null and b/ios/assets/fonts/SourceHanSansCN-Bold.otf differ diff --git a/ios/assets/fonts/SourceHanSansCN-Medium.otf b/ios/assets/fonts/SourceHanSansCN-Medium.otf new file mode 100644 index 0000000..53e03e0 Binary files /dev/null and b/ios/assets/fonts/SourceHanSansCN-Medium.otf differ diff --git a/ios/assets/fonts/SourceHanSansCN-Regular.otf b/ios/assets/fonts/SourceHanSansCN-Regular.otf new file mode 100644 index 0000000..886f82f Binary files /dev/null and b/ios/assets/fonts/SourceHanSansCN-Regular.otf differ diff --git a/ios/assets/images/3.0x/Contact_Female.webp b/ios/assets/images/3.0x/Contact_Female.webp new file mode 100644 index 0000000..36b7507 Binary files /dev/null and b/ios/assets/images/3.0x/Contact_Female.webp differ diff --git a/ios/assets/images/3.0x/Contact_Male.webp b/ios/assets/images/3.0x/Contact_Male.webp new file mode 100644 index 0000000..237a044 Binary files /dev/null and b/ios/assets/images/3.0x/Contact_Male.webp differ diff --git a/ios/assets/images/3.0x/add_addressicon.png b/ios/assets/images/3.0x/add_addressicon.png new file mode 100644 index 0000000..0176a84 Binary files /dev/null and b/ios/assets/images/3.0x/add_addressicon.png differ diff --git a/ios/assets/images/3.0x/bar_close.png b/ios/assets/images/3.0x/bar_close.png new file mode 100644 index 0000000..4ef521c Binary files /dev/null and b/ios/assets/images/3.0x/bar_close.png differ diff --git a/ios/assets/images/3.0x/bsc.webp b/ios/assets/images/3.0x/bsc.webp new file mode 100644 index 0000000..260f190 Binary files /dev/null and b/ios/assets/images/3.0x/bsc.webp differ diff --git a/ios/assets/images/3.0x/contacts_add_newmessage.png b/ios/assets/images/3.0x/contacts_add_newmessage.png new file mode 100644 index 0000000..b140f01 Binary files /dev/null and b/ios/assets/images/3.0x/contacts_add_newmessage.png differ diff --git a/ios/assets/images/3.0x/def_avatar.png b/ios/assets/images/3.0x/def_avatar.png new file mode 100644 index 0000000..bb53f59 Binary files /dev/null and b/ios/assets/images/3.0x/def_avatar.png differ diff --git a/ios/assets/images/3.0x/favorite.webp b/ios/assets/images/3.0x/favorite.webp new file mode 100644 index 0000000..b6c28cb Binary files /dev/null and b/ios/assets/images/3.0x/favorite.webp differ diff --git a/ios/assets/images/3.0x/ic_add_friend.webp b/ios/assets/images/3.0x/ic_add_friend.webp new file mode 100644 index 0000000..fb12ae5 Binary files /dev/null and b/ios/assets/images/3.0x/ic_add_friend.webp differ diff --git a/ios/assets/images/3.0x/ic_delete.webp b/ios/assets/images/3.0x/ic_delete.webp new file mode 100644 index 0000000..5f33882 Binary files /dev/null and b/ios/assets/images/3.0x/ic_delete.webp differ diff --git a/ios/assets/images/3.0x/ic_no_data.webp b/ios/assets/images/3.0x/ic_no_data.webp new file mode 100644 index 0000000..01020e1 Binary files /dev/null and b/ios/assets/images/3.0x/ic_no_data.webp differ diff --git a/ios/assets/images/3.0x/ic_right_arrow_black.webp b/ios/assets/images/3.0x/ic_right_arrow_black.webp new file mode 100644 index 0000000..01b0546 Binary files /dev/null and b/ios/assets/images/3.0x/ic_right_arrow_black.webp differ diff --git a/ios/assets/images/3.0x/ic_right_arrow_grey.webp b/ios/assets/images/3.0x/ic_right_arrow_grey.webp new file mode 100644 index 0000000..e6ddaa8 Binary files /dev/null and b/ios/assets/images/3.0x/ic_right_arrow_grey.webp differ diff --git a/ios/assets/images/3.0x/right_more.png b/ios/assets/images/3.0x/right_more.png new file mode 100644 index 0000000..ca5ee29 Binary files /dev/null and b/ios/assets/images/3.0x/right_more.png differ diff --git a/ios/assets/images/3.0x/search_black.webp b/ios/assets/images/3.0x/search_black.webp new file mode 100644 index 0000000..dc78b42 Binary files /dev/null and b/ios/assets/images/3.0x/search_black.webp differ diff --git a/ios/assets/images/3.0x/search_white.png b/ios/assets/images/3.0x/search_white.png new file mode 100644 index 0000000..9ce06ce Binary files /dev/null and b/ios/assets/images/3.0x/search_white.png differ diff --git a/ios/assets/images/3.0x/sharemore_pay.png b/ios/assets/images/3.0x/sharemore_pay.png new file mode 100644 index 0000000..0ebd048 Binary files /dev/null and b/ios/assets/images/3.0x/sharemore_pay.png differ diff --git a/ios/assets/images/3.0x/tabbar_chat_c.webp b/ios/assets/images/3.0x/tabbar_chat_c.webp new file mode 100644 index 0000000..431542e Binary files /dev/null and b/ios/assets/images/3.0x/tabbar_chat_c.webp differ diff --git a/ios/assets/images/3.0x/tabbar_chat_s.webp b/ios/assets/images/3.0x/tabbar_chat_s.webp new file mode 100644 index 0000000..b3f5455 Binary files /dev/null and b/ios/assets/images/3.0x/tabbar_chat_s.webp differ diff --git a/ios/assets/images/3.0x/tabbar_contacts_c.webp b/ios/assets/images/3.0x/tabbar_contacts_c.webp new file mode 100644 index 0000000..7dfb617 Binary files /dev/null and b/ios/assets/images/3.0x/tabbar_contacts_c.webp differ diff --git a/ios/assets/images/3.0x/tabbar_contacts_s.webp b/ios/assets/images/3.0x/tabbar_contacts_s.webp new file mode 100644 index 0000000..203aff6 Binary files /dev/null and b/ios/assets/images/3.0x/tabbar_contacts_s.webp differ diff --git a/ios/assets/images/3.0x/tabbar_discover_c.webp b/ios/assets/images/3.0x/tabbar_discover_c.webp new file mode 100644 index 0000000..81ac425 Binary files /dev/null and b/ios/assets/images/3.0x/tabbar_discover_c.webp differ diff --git a/ios/assets/images/3.0x/tabbar_discover_s.webp b/ios/assets/images/3.0x/tabbar_discover_s.webp new file mode 100644 index 0000000..64fe53b Binary files /dev/null and b/ios/assets/images/3.0x/tabbar_discover_s.webp differ diff --git a/ios/assets/images/3.0x/tabbar_me_c.webp b/ios/assets/images/3.0x/tabbar_me_c.webp new file mode 100644 index 0000000..533343b Binary files /dev/null and b/ios/assets/images/3.0x/tabbar_me_c.webp differ diff --git a/ios/assets/images/3.0x/tabbar_me_s.webp b/ios/assets/images/3.0x/tabbar_me_s.webp new file mode 100644 index 0000000..e966492 Binary files /dev/null and b/ios/assets/images/3.0x/tabbar_me_s.webp differ diff --git a/ios/assets/images/calling_face.png b/ios/assets/images/calling_face.png new file mode 100644 index 0000000..b6a7cb9 Binary files /dev/null and b/ios/assets/images/calling_face.png differ diff --git a/ios/assets/images/chat/ChatRomm_ToolPanel_Icon_Voipvoice@3x.png b/ios/assets/images/chat/ChatRomm_ToolPanel_Icon_Voipvoice@3x.png new file mode 100644 index 0000000..3fbc7da Binary files /dev/null and b/ios/assets/images/chat/ChatRomm_ToolPanel_Icon_Voipvoice@3x.png differ diff --git a/ios/assets/images/chat/ChatRomm_ToolPanel_Icon_Wallet@3x.png b/ios/assets/images/chat/ChatRomm_ToolPanel_Icon_Wallet@3x.png new file mode 100644 index 0000000..972274f Binary files /dev/null and b/ios/assets/images/chat/ChatRomm_ToolPanel_Icon_Wallet@3x.png differ diff --git a/ios/assets/images/chat/flip_camera_icon_nor.webp b/ios/assets/images/chat/flip_camera_icon_nor.webp new file mode 100644 index 0000000..271389e Binary files /dev/null and b/ios/assets/images/chat/flip_camera_icon_nor.webp differ diff --git a/ios/assets/images/chat/ic_Emotion.webp b/ios/assets/images/chat/ic_Emotion.webp new file mode 100644 index 0000000..716e1c9 Binary files /dev/null and b/ios/assets/images/chat/ic_Emotion.webp differ diff --git a/ios/assets/images/chat/ic_Keyboard.webp b/ios/assets/images/chat/ic_Keyboard.webp new file mode 100644 index 0000000..23e5b11 Binary files /dev/null and b/ios/assets/images/chat/ic_Keyboard.webp differ diff --git a/ios/assets/images/chat/ic_chat_more.webp b/ios/assets/images/chat/ic_chat_more.webp new file mode 100644 index 0000000..3552857 Binary files /dev/null and b/ios/assets/images/chat/ic_chat_more.webp differ diff --git a/ios/assets/images/chat/ic_chat_voice.webp b/ios/assets/images/chat/ic_chat_voice.webp new file mode 100644 index 0000000..0ebfbe2 Binary files /dev/null and b/ios/assets/images/chat/ic_chat_voice.webp differ diff --git a/ios/assets/images/chat/ic_details_add.png b/ios/assets/images/chat/ic_details_add.png new file mode 100644 index 0000000..53737ca Binary files /dev/null and b/ios/assets/images/chat/ic_details_add.png differ diff --git a/ios/assets/images/chat/ic_details_camera.webp b/ios/assets/images/chat/ic_details_camera.webp new file mode 100644 index 0000000..fe83d04 Binary files /dev/null and b/ios/assets/images/chat/ic_details_camera.webp differ diff --git a/ios/assets/images/chat/ic_details_card.webp b/ios/assets/images/chat/ic_details_card.webp new file mode 100644 index 0000000..d99a68b Binary files /dev/null and b/ios/assets/images/chat/ic_details_card.webp differ diff --git a/ios/assets/images/chat/ic_details_favorite.webp b/ios/assets/images/chat/ic_details_favorite.webp new file mode 100644 index 0000000..190ae40 Binary files /dev/null and b/ios/assets/images/chat/ic_details_favorite.webp differ diff --git a/ios/assets/images/chat/ic_details_file.webp b/ios/assets/images/chat/ic_details_file.webp new file mode 100644 index 0000000..c8d75ab Binary files /dev/null and b/ios/assets/images/chat/ic_details_file.webp differ diff --git a/ios/assets/images/chat/ic_details_localtion.webp b/ios/assets/images/chat/ic_details_localtion.webp new file mode 100644 index 0000000..fcd628d Binary files /dev/null and b/ios/assets/images/chat/ic_details_localtion.webp differ diff --git a/ios/assets/images/chat/ic_details_media.webp b/ios/assets/images/chat/ic_details_media.webp new file mode 100644 index 0000000..2806229 Binary files /dev/null and b/ios/assets/images/chat/ic_details_media.webp differ diff --git a/ios/assets/images/chat/ic_details_photo.webp b/ios/assets/images/chat/ic_details_photo.webp new file mode 100644 index 0000000..27607e2 Binary files /dev/null and b/ios/assets/images/chat/ic_details_photo.webp differ diff --git a/ios/assets/images/chat/ic_details_red.webp b/ios/assets/images/chat/ic_details_red.webp new file mode 100644 index 0000000..5a0b66b Binary files /dev/null and b/ios/assets/images/chat/ic_details_red.webp differ diff --git a/ios/assets/images/chat/ic_details_transfer.webp b/ios/assets/images/chat/ic_details_transfer.webp new file mode 100644 index 0000000..f109cfb Binary files /dev/null and b/ios/assets/images/chat/ic_details_transfer.webp differ diff --git a/ios/assets/images/chat/ic_details_video.webp b/ios/assets/images/chat/ic_details_video.webp new file mode 100644 index 0000000..44a6db6 Binary files /dev/null and b/ios/assets/images/chat/ic_details_video.webp differ diff --git a/ios/assets/images/chat/ic_voice.webp b/ios/assets/images/chat/ic_voice.webp new file mode 100644 index 0000000..38158f0 Binary files /dev/null and b/ios/assets/images/chat/ic_voice.webp differ diff --git a/ios/assets/images/chat/icon_sight_close.png b/ios/assets/images/chat/icon_sight_close.png new file mode 100644 index 0000000..da47e4e Binary files /dev/null and b/ios/assets/images/chat/icon_sight_close.png differ diff --git a/ios/assets/images/chat/sound_left_0.webp b/ios/assets/images/chat/sound_left_0.webp new file mode 100644 index 0000000..b1d56e0 Binary files /dev/null and b/ios/assets/images/chat/sound_left_0.webp differ diff --git a/ios/assets/images/chat/sound_left_1.webp b/ios/assets/images/chat/sound_left_1.webp new file mode 100644 index 0000000..2d9950f Binary files /dev/null and b/ios/assets/images/chat/sound_left_1.webp differ diff --git a/ios/assets/images/chat/sound_left_2.webp b/ios/assets/images/chat/sound_left_2.webp new file mode 100644 index 0000000..ae13a99 Binary files /dev/null and b/ios/assets/images/chat/sound_left_2.webp differ diff --git a/ios/assets/images/chat/sound_left_3.webp b/ios/assets/images/chat/sound_left_3.webp new file mode 100644 index 0000000..b1d56e0 Binary files /dev/null and b/ios/assets/images/chat/sound_left_3.webp differ diff --git a/ios/assets/images/chat/sound_right_0.png b/ios/assets/images/chat/sound_right_0.png new file mode 100644 index 0000000..64208e6 Binary files /dev/null and b/ios/assets/images/chat/sound_right_0.png differ diff --git a/ios/assets/images/chat/sound_right_1.webp b/ios/assets/images/chat/sound_right_1.webp new file mode 100644 index 0000000..08ed902 Binary files /dev/null and b/ios/assets/images/chat/sound_right_1.webp differ diff --git a/ios/assets/images/chat/sound_right_2.webp b/ios/assets/images/chat/sound_right_2.webp new file mode 100644 index 0000000..34258f9 Binary files /dev/null and b/ios/assets/images/chat/sound_right_2.webp differ diff --git a/ios/assets/images/chat/sound_right_3.png b/ios/assets/images/chat/sound_right_3.png new file mode 100644 index 0000000..232155e Binary files /dev/null and b/ios/assets/images/chat/sound_right_3.png differ diff --git a/ios/assets/images/chat/voice_volume_1.webp b/ios/assets/images/chat/voice_volume_1.webp new file mode 100644 index 0000000..5048471 Binary files /dev/null and b/ios/assets/images/chat/voice_volume_1.webp differ diff --git a/ios/assets/images/chat/voice_volume_2.webp b/ios/assets/images/chat/voice_volume_2.webp new file mode 100644 index 0000000..a73753f Binary files /dev/null and b/ios/assets/images/chat/voice_volume_2.webp differ diff --git a/ios/assets/images/chat/voice_volume_3.webp b/ios/assets/images/chat/voice_volume_3.webp new file mode 100644 index 0000000..80db508 Binary files /dev/null and b/ios/assets/images/chat/voice_volume_3.webp differ diff --git a/ios/assets/images/chat/voice_volume_4.webp b/ios/assets/images/chat/voice_volume_4.webp new file mode 100644 index 0000000..36aff56 Binary files /dev/null and b/ios/assets/images/chat/voice_volume_4.webp differ diff --git a/ios/assets/images/chat/voice_volume_5.webp b/ios/assets/images/chat/voice_volume_5.webp new file mode 100644 index 0000000..059cf5f Binary files /dev/null and b/ios/assets/images/chat/voice_volume_5.webp differ diff --git a/ios/assets/images/chat/voice_volume_6.webp b/ios/assets/images/chat/voice_volume_6.webp new file mode 100644 index 0000000..055ee84 Binary files /dev/null and b/ios/assets/images/chat/voice_volume_6.webp differ diff --git a/ios/assets/images/chat/voice_volume_7.webp b/ios/assets/images/chat/voice_volume_7.webp new file mode 100644 index 0000000..6811565 Binary files /dev/null and b/ios/assets/images/chat/voice_volume_7.webp differ diff --git a/ios/assets/images/contact/GameCenterH5GameMenuBtn@2x.png b/ios/assets/images/contact/GameCenterH5GameMenuBtn@2x.png new file mode 100644 index 0000000..abcbe6d Binary files /dev/null and b/ios/assets/images/contact/GameCenterH5GameMenuBtn@2x.png differ diff --git a/ios/assets/images/contact/GroupVerify_NewInvitation_Icon@3x.png b/ios/assets/images/contact/GroupVerify_NewInvitation_Icon@3x.png new file mode 100644 index 0000000..bd0e2e3 Binary files /dev/null and b/ios/assets/images/contact/GroupVerify_NewInvitation_Icon@3x.png differ diff --git a/ios/assets/images/contact/ic_contact_add.webp b/ios/assets/images/contact/ic_contact_add.webp new file mode 100644 index 0000000..818ab19 Binary files /dev/null and b/ios/assets/images/contact/ic_contact_add.webp differ diff --git a/ios/assets/images/contact/ic_contacts_details.png b/ios/assets/images/contact/ic_contacts_details.png new file mode 100644 index 0000000..ca5ee29 Binary files /dev/null and b/ios/assets/images/contact/ic_contacts_details.png differ diff --git a/ios/assets/images/contact/ic_group.webp b/ios/assets/images/contact/ic_group.webp new file mode 100644 index 0000000..494beb5 Binary files /dev/null and b/ios/assets/images/contact/ic_group.webp differ diff --git a/ios/assets/images/contact/ic_new_friend.webp b/ios/assets/images/contact/ic_new_friend.webp new file mode 100644 index 0000000..dbe5076 Binary files /dev/null and b/ios/assets/images/contact/ic_new_friend.webp differ diff --git a/ios/assets/images/contact/ic_no_public.webp b/ios/assets/images/contact/ic_no_public.webp new file mode 100644 index 0000000..cfe9eeb Binary files /dev/null and b/ios/assets/images/contact/ic_no_public.webp differ diff --git a/ios/assets/images/contact/ic_offical.webp b/ios/assets/images/contact/ic_offical.webp new file mode 100644 index 0000000..b6b77e6 Binary files /dev/null and b/ios/assets/images/contact/ic_offical.webp differ diff --git a/ios/assets/images/contact/ic_reda.webp b/ios/assets/images/contact/ic_reda.webp new file mode 100644 index 0000000..d28c49a Binary files /dev/null and b/ios/assets/images/contact/ic_reda.webp differ diff --git a/ios/assets/images/contact/ic_scanqr.webp b/ios/assets/images/contact/ic_scanqr.webp new file mode 100644 index 0000000..51132e1 Binary files /dev/null and b/ios/assets/images/contact/ic_scanqr.webp differ diff --git a/ios/assets/images/contact/ic_search_wework.webp b/ios/assets/images/contact/ic_search_wework.webp new file mode 100644 index 0000000..0f4226b Binary files /dev/null and b/ios/assets/images/contact/ic_search_wework.webp differ diff --git a/ios/assets/images/contact/ic_tag.webp b/ios/assets/images/contact/ic_tag.webp new file mode 100644 index 0000000..a7c5dda Binary files /dev/null and b/ios/assets/images/contact/ic_tag.webp differ diff --git a/ios/assets/images/contact/ic_video.png b/ios/assets/images/contact/ic_video.png new file mode 100644 index 0000000..c3e23bb Binary files /dev/null and b/ios/assets/images/contact/ic_video.png differ diff --git a/ios/assets/images/contact/ic_voice.png b/ios/assets/images/contact/ic_voice.png new file mode 100644 index 0000000..78b5f67 Binary files /dev/null and b/ios/assets/images/contact/ic_voice.png differ diff --git a/ios/assets/images/discover/ff_Icon_album.webp b/ios/assets/images/discover/ff_Icon_album.webp new file mode 100644 index 0000000..ee333af Binary files /dev/null and b/ios/assets/images/discover/ff_Icon_album.webp differ diff --git a/ios/assets/images/discover/ff_Icon_bottle.webp b/ios/assets/images/discover/ff_Icon_bottle.webp new file mode 100644 index 0000000..47a0eb8 Binary files /dev/null and b/ios/assets/images/discover/ff_Icon_bottle.webp differ diff --git a/ios/assets/images/discover/ff_Icon_browse.webp b/ios/assets/images/discover/ff_Icon_browse.webp new file mode 100644 index 0000000..51f461f Binary files /dev/null and b/ios/assets/images/discover/ff_Icon_browse.webp differ diff --git a/ios/assets/images/discover/ff_Icon_nearby.webp b/ios/assets/images/discover/ff_Icon_nearby.webp new file mode 100644 index 0000000..ed2feea Binary files /dev/null and b/ios/assets/images/discover/ff_Icon_nearby.webp differ diff --git a/ios/assets/images/discover/ff_Icon_qr_code.webp b/ios/assets/images/discover/ff_Icon_qr_code.webp new file mode 100644 index 0000000..0283911 Binary files /dev/null and b/ios/assets/images/discover/ff_Icon_qr_code.webp differ diff --git a/ios/assets/images/discover/ff_Icon_search.webp b/ios/assets/images/discover/ff_Icon_search.webp new file mode 100644 index 0000000..a4be3db Binary files /dev/null and b/ios/assets/images/discover/ff_Icon_search.webp differ diff --git a/ios/assets/images/discover/ff_Icon_shake.webp b/ios/assets/images/discover/ff_Icon_shake.webp new file mode 100644 index 0000000..41a6856 Binary files /dev/null and b/ios/assets/images/discover/ff_Icon_shake.webp differ diff --git a/ios/assets/images/discover/game_center_h5.webp b/ios/assets/images/discover/game_center_h5.webp new file mode 100644 index 0000000..fadf3a7 Binary files /dev/null and b/ios/assets/images/discover/game_center_h5.webp differ diff --git a/ios/assets/images/discover/mini_program.webp b/ios/assets/images/discover/mini_program.webp new file mode 100644 index 0000000..cbaad1e Binary files /dev/null and b/ios/assets/images/discover/mini_program.webp differ diff --git a/ios/assets/images/emoji/sg012.png b/ios/assets/images/emoji/sg012.png new file mode 100644 index 0000000..e3338da Binary files /dev/null and b/ios/assets/images/emoji/sg012.png differ diff --git a/ios/assets/images/emoji/sg013.png b/ios/assets/images/emoji/sg013.png new file mode 100644 index 0000000..d0218c5 Binary files /dev/null and b/ios/assets/images/emoji/sg013.png differ diff --git a/ios/assets/images/emoji/sg014.png b/ios/assets/images/emoji/sg014.png new file mode 100644 index 0000000..06568c2 Binary files /dev/null and b/ios/assets/images/emoji/sg014.png differ diff --git a/ios/assets/images/emoji/sg015.png b/ios/assets/images/emoji/sg015.png new file mode 100644 index 0000000..c5cc155 Binary files /dev/null and b/ios/assets/images/emoji/sg015.png differ diff --git a/ios/assets/images/emoji/sg016.png b/ios/assets/images/emoji/sg016.png new file mode 100644 index 0000000..e77a4da Binary files /dev/null and b/ios/assets/images/emoji/sg016.png differ diff --git a/ios/assets/images/emoji/sg017.png b/ios/assets/images/emoji/sg017.png new file mode 100644 index 0000000..845f290 Binary files /dev/null and b/ios/assets/images/emoji/sg017.png differ diff --git a/ios/assets/images/emoji/sg018.png b/ios/assets/images/emoji/sg018.png new file mode 100644 index 0000000..3d5212e Binary files /dev/null and b/ios/assets/images/emoji/sg018.png differ diff --git a/ios/assets/images/emoji/sg019.png b/ios/assets/images/emoji/sg019.png new file mode 100644 index 0000000..929f2cf Binary files /dev/null and b/ios/assets/images/emoji/sg019.png differ diff --git a/ios/assets/images/emoji/sg020.png b/ios/assets/images/emoji/sg020.png new file mode 100644 index 0000000..6c911b6 Binary files /dev/null and b/ios/assets/images/emoji/sg020.png differ diff --git a/ios/assets/images/emoji/sg021.png b/ios/assets/images/emoji/sg021.png new file mode 100644 index 0000000..ac5f0f7 Binary files /dev/null and b/ios/assets/images/emoji/sg021.png differ diff --git a/ios/assets/images/emoji/sg022.png b/ios/assets/images/emoji/sg022.png new file mode 100644 index 0000000..d25887b Binary files /dev/null and b/ios/assets/images/emoji/sg022.png differ diff --git a/ios/assets/images/emoji/sg023.png b/ios/assets/images/emoji/sg023.png new file mode 100644 index 0000000..3ee4baa Binary files /dev/null and b/ios/assets/images/emoji/sg023.png differ diff --git a/ios/assets/images/emoji/sg024.png b/ios/assets/images/emoji/sg024.png new file mode 100644 index 0000000..8a4fbd4 Binary files /dev/null and b/ios/assets/images/emoji/sg024.png differ diff --git a/ios/assets/images/emoji/sg025.png b/ios/assets/images/emoji/sg025.png new file mode 100644 index 0000000..2c4fc74 Binary files /dev/null and b/ios/assets/images/emoji/sg025.png differ diff --git a/ios/assets/images/emoji/sg026.png b/ios/assets/images/emoji/sg026.png new file mode 100644 index 0000000..2b59402 Binary files /dev/null and b/ios/assets/images/emoji/sg026.png differ diff --git a/ios/assets/images/emoji/sg027.png b/ios/assets/images/emoji/sg027.png new file mode 100644 index 0000000..7fae81d Binary files /dev/null and b/ios/assets/images/emoji/sg027.png differ diff --git a/ios/assets/images/emoji/sg028.png b/ios/assets/images/emoji/sg028.png new file mode 100644 index 0000000..52cdb7a Binary files /dev/null and b/ios/assets/images/emoji/sg028.png differ diff --git a/ios/assets/images/emoji/sg029.png b/ios/assets/images/emoji/sg029.png new file mode 100644 index 0000000..838fec8 Binary files /dev/null and b/ios/assets/images/emoji/sg029.png differ diff --git a/ios/assets/images/emoji/sg030.png b/ios/assets/images/emoji/sg030.png new file mode 100644 index 0000000..688cacf Binary files /dev/null and b/ios/assets/images/emoji/sg030.png differ diff --git a/ios/assets/images/emoji/sg031.png b/ios/assets/images/emoji/sg031.png new file mode 100644 index 0000000..cca17b6 Binary files /dev/null and b/ios/assets/images/emoji/sg031.png differ diff --git a/ios/assets/images/emoji/sg032.png b/ios/assets/images/emoji/sg032.png new file mode 100644 index 0000000..f7a8375 Binary files /dev/null and b/ios/assets/images/emoji/sg032.png differ diff --git a/ios/assets/images/emoji/sg033.png b/ios/assets/images/emoji/sg033.png new file mode 100644 index 0000000..2e1be8c Binary files /dev/null and b/ios/assets/images/emoji/sg033.png differ diff --git a/ios/assets/images/emoji/sg034.png b/ios/assets/images/emoji/sg034.png new file mode 100644 index 0000000..d156106 Binary files /dev/null and b/ios/assets/images/emoji/sg034.png differ diff --git a/ios/assets/images/emoji/sg035.png b/ios/assets/images/emoji/sg035.png new file mode 100644 index 0000000..59ffe75 Binary files /dev/null and b/ios/assets/images/emoji/sg035.png differ diff --git a/ios/assets/images/emoji/sg036.png b/ios/assets/images/emoji/sg036.png new file mode 100644 index 0000000..bfa3c0b Binary files /dev/null and b/ios/assets/images/emoji/sg036.png differ diff --git a/ios/assets/images/emoji/sg037.png b/ios/assets/images/emoji/sg037.png new file mode 100644 index 0000000..519bf88 Binary files /dev/null and b/ios/assets/images/emoji/sg037.png differ diff --git a/ios/assets/images/emoji/sg038.png b/ios/assets/images/emoji/sg038.png new file mode 100644 index 0000000..2dee27b Binary files /dev/null and b/ios/assets/images/emoji/sg038.png differ diff --git a/ios/assets/images/emoji/sg040.png b/ios/assets/images/emoji/sg040.png new file mode 100644 index 0000000..fd4df24 Binary files /dev/null and b/ios/assets/images/emoji/sg040.png differ diff --git a/ios/assets/images/emoji/sg041.png b/ios/assets/images/emoji/sg041.png new file mode 100644 index 0000000..d514d47 Binary files /dev/null and b/ios/assets/images/emoji/sg041.png differ diff --git a/ios/assets/images/emoji/sg042.png b/ios/assets/images/emoji/sg042.png new file mode 100644 index 0000000..84778ab Binary files /dev/null and b/ios/assets/images/emoji/sg042.png differ diff --git a/ios/assets/images/emoji/sg043.png b/ios/assets/images/emoji/sg043.png new file mode 100644 index 0000000..dc7eecb Binary files /dev/null and b/ios/assets/images/emoji/sg043.png differ diff --git a/ios/assets/images/emoji/sg044.png b/ios/assets/images/emoji/sg044.png new file mode 100644 index 0000000..ca5ee9a Binary files /dev/null and b/ios/assets/images/emoji/sg044.png differ diff --git a/ios/assets/images/emoji/sg045.png b/ios/assets/images/emoji/sg045.png new file mode 100644 index 0000000..b320132 Binary files /dev/null and b/ios/assets/images/emoji/sg045.png differ diff --git a/ios/assets/images/emoji/sg046.png b/ios/assets/images/emoji/sg046.png new file mode 100644 index 0000000..2d8b68d Binary files /dev/null and b/ios/assets/images/emoji/sg046.png differ diff --git a/ios/assets/images/emoji/sg047.png b/ios/assets/images/emoji/sg047.png new file mode 100644 index 0000000..7b830c7 Binary files /dev/null and b/ios/assets/images/emoji/sg047.png differ diff --git a/ios/assets/images/emoji/sg049.png b/ios/assets/images/emoji/sg049.png new file mode 100644 index 0000000..1f7763b Binary files /dev/null and b/ios/assets/images/emoji/sg049.png differ diff --git a/ios/assets/images/emoji/sg050.png b/ios/assets/images/emoji/sg050.png new file mode 100644 index 0000000..2d99dce Binary files /dev/null and b/ios/assets/images/emoji/sg050.png differ diff --git a/ios/assets/images/emoji/sg051.png b/ios/assets/images/emoji/sg051.png new file mode 100644 index 0000000..e731351 Binary files /dev/null and b/ios/assets/images/emoji/sg051.png differ diff --git a/ios/assets/images/emoji/sg052.png b/ios/assets/images/emoji/sg052.png new file mode 100644 index 0000000..373c918 Binary files /dev/null and b/ios/assets/images/emoji/sg052.png differ diff --git a/ios/assets/images/emoji/sg053.png b/ios/assets/images/emoji/sg053.png new file mode 100644 index 0000000..f355146 Binary files /dev/null and b/ios/assets/images/emoji/sg053.png differ diff --git a/ios/assets/images/emoji/sg054.png b/ios/assets/images/emoji/sg054.png new file mode 100644 index 0000000..7672f1f Binary files /dev/null and b/ios/assets/images/emoji/sg054.png differ diff --git a/ios/assets/images/emoji/sg055.png b/ios/assets/images/emoji/sg055.png new file mode 100644 index 0000000..c0bfd8e Binary files /dev/null and b/ios/assets/images/emoji/sg055.png differ diff --git a/ios/assets/images/emoji/sg056.png b/ios/assets/images/emoji/sg056.png new file mode 100644 index 0000000..469386f Binary files /dev/null and b/ios/assets/images/emoji/sg056.png differ diff --git a/ios/assets/images/emoji/sg057.png b/ios/assets/images/emoji/sg057.png new file mode 100644 index 0000000..97708c7 Binary files /dev/null and b/ios/assets/images/emoji/sg057.png differ diff --git a/ios/assets/images/emoji/sg058.png b/ios/assets/images/emoji/sg058.png new file mode 100644 index 0000000..6238725 Binary files /dev/null and b/ios/assets/images/emoji/sg058.png differ diff --git a/ios/assets/images/emoji/sg060.png b/ios/assets/images/emoji/sg060.png new file mode 100644 index 0000000..19dc564 Binary files /dev/null and b/ios/assets/images/emoji/sg060.png differ diff --git a/ios/assets/images/emoji/sg061.png b/ios/assets/images/emoji/sg061.png new file mode 100644 index 0000000..2c69738 Binary files /dev/null and b/ios/assets/images/emoji/sg061.png differ diff --git a/ios/assets/images/emoji/sg062.png b/ios/assets/images/emoji/sg062.png new file mode 100644 index 0000000..ad9b0af Binary files /dev/null and b/ios/assets/images/emoji/sg062.png differ diff --git a/ios/assets/images/emoji/sg064.png b/ios/assets/images/emoji/sg064.png new file mode 100644 index 0000000..b1803c3 Binary files /dev/null and b/ios/assets/images/emoji/sg064.png differ diff --git a/ios/assets/images/emoji/sg065.png b/ios/assets/images/emoji/sg065.png new file mode 100644 index 0000000..1674fc4 Binary files /dev/null and b/ios/assets/images/emoji/sg065.png differ diff --git a/ios/assets/images/emoji/sg066.png b/ios/assets/images/emoji/sg066.png new file mode 100644 index 0000000..bc25c6d Binary files /dev/null and b/ios/assets/images/emoji/sg066.png differ diff --git a/ios/assets/images/emoji/sg067.png b/ios/assets/images/emoji/sg067.png new file mode 100644 index 0000000..d6601f2 Binary files /dev/null and b/ios/assets/images/emoji/sg067.png differ diff --git a/ios/assets/images/emoji/sg068.png b/ios/assets/images/emoji/sg068.png new file mode 100644 index 0000000..b10f8d8 Binary files /dev/null and b/ios/assets/images/emoji/sg068.png differ diff --git a/ios/assets/images/emoji/sg071.png b/ios/assets/images/emoji/sg071.png new file mode 100644 index 0000000..156dd4c Binary files /dev/null and b/ios/assets/images/emoji/sg071.png differ diff --git a/ios/assets/images/emoji/sg072.png b/ios/assets/images/emoji/sg072.png new file mode 100644 index 0000000..60f075c Binary files /dev/null and b/ios/assets/images/emoji/sg072.png differ diff --git a/ios/assets/images/emoji/sg073.png b/ios/assets/images/emoji/sg073.png new file mode 100644 index 0000000..4429d67 Binary files /dev/null and b/ios/assets/images/emoji/sg073.png differ diff --git a/ios/assets/images/emoji/sg074.png b/ios/assets/images/emoji/sg074.png new file mode 100644 index 0000000..38b5cd7 Binary files /dev/null and b/ios/assets/images/emoji/sg074.png differ diff --git a/ios/assets/images/emoji/sg075.png b/ios/assets/images/emoji/sg075.png new file mode 100644 index 0000000..b53e6c2 Binary files /dev/null and b/ios/assets/images/emoji/sg075.png differ diff --git a/ios/assets/images/emoji/sg077.png b/ios/assets/images/emoji/sg077.png new file mode 100644 index 0000000..3437d24 Binary files /dev/null and b/ios/assets/images/emoji/sg077.png differ diff --git a/ios/assets/images/emoji/sg081.png b/ios/assets/images/emoji/sg081.png new file mode 100644 index 0000000..8b73202 Binary files /dev/null and b/ios/assets/images/emoji/sg081.png differ diff --git a/ios/assets/images/emoji/sg082.png b/ios/assets/images/emoji/sg082.png new file mode 100644 index 0000000..399500e Binary files /dev/null and b/ios/assets/images/emoji/sg082.png differ diff --git a/ios/assets/images/emoji/sg083.png b/ios/assets/images/emoji/sg083.png new file mode 100644 index 0000000..5ae9814 Binary files /dev/null and b/ios/assets/images/emoji/sg083.png differ diff --git a/ios/assets/images/emoji/sg084.png b/ios/assets/images/emoji/sg084.png new file mode 100644 index 0000000..9909ea0 Binary files /dev/null and b/ios/assets/images/emoji/sg084.png differ diff --git a/ios/assets/images/emoji/sg085.png b/ios/assets/images/emoji/sg085.png new file mode 100644 index 0000000..75be52e Binary files /dev/null and b/ios/assets/images/emoji/sg085.png differ diff --git a/ios/assets/images/emoji/sg086.png b/ios/assets/images/emoji/sg086.png new file mode 100644 index 0000000..4254a04 Binary files /dev/null and b/ios/assets/images/emoji/sg086.png differ diff --git a/ios/assets/images/emoji/sg087.png b/ios/assets/images/emoji/sg087.png new file mode 100644 index 0000000..4a646df Binary files /dev/null and b/ios/assets/images/emoji/sg087.png differ diff --git a/ios/assets/images/emoji/sg088.png b/ios/assets/images/emoji/sg088.png new file mode 100644 index 0000000..2a6ef8b Binary files /dev/null and b/ios/assets/images/emoji/sg088.png differ diff --git a/ios/assets/images/emoji/sg089.png b/ios/assets/images/emoji/sg089.png new file mode 100644 index 0000000..a9171bd Binary files /dev/null and b/ios/assets/images/emoji/sg089.png differ diff --git a/ios/assets/images/emoji/sg090.png b/ios/assets/images/emoji/sg090.png new file mode 100644 index 0000000..0be82f6 Binary files /dev/null and b/ios/assets/images/emoji/sg090.png differ diff --git a/ios/assets/images/emoji/sg1.png b/ios/assets/images/emoji/sg1.png new file mode 100644 index 0000000..3c5ab3f Binary files /dev/null and b/ios/assets/images/emoji/sg1.png differ diff --git a/ios/assets/images/emoji/sg10.png b/ios/assets/images/emoji/sg10.png new file mode 100644 index 0000000..ab70123 Binary files /dev/null and b/ios/assets/images/emoji/sg10.png differ diff --git a/ios/assets/images/emoji/sg100.png b/ios/assets/images/emoji/sg100.png new file mode 100644 index 0000000..7c06653 Binary files /dev/null and b/ios/assets/images/emoji/sg100.png differ diff --git a/ios/assets/images/emoji/sg105.png b/ios/assets/images/emoji/sg105.png new file mode 100644 index 0000000..0516c75 Binary files /dev/null and b/ios/assets/images/emoji/sg105.png differ diff --git a/ios/assets/images/emoji/sg11.png b/ios/assets/images/emoji/sg11.png new file mode 100644 index 0000000..e3338da Binary files /dev/null and b/ios/assets/images/emoji/sg11.png differ diff --git a/ios/assets/images/emoji/sg115.png b/ios/assets/images/emoji/sg115.png new file mode 100644 index 0000000..5c56212 Binary files /dev/null and b/ios/assets/images/emoji/sg115.png differ diff --git a/ios/assets/images/emoji/sg12.png b/ios/assets/images/emoji/sg12.png new file mode 100644 index 0000000..d0218c5 Binary files /dev/null and b/ios/assets/images/emoji/sg12.png differ diff --git a/ios/assets/images/emoji/sg13.png b/ios/assets/images/emoji/sg13.png new file mode 100644 index 0000000..06568c2 Binary files /dev/null and b/ios/assets/images/emoji/sg13.png differ diff --git a/ios/assets/images/emoji/sg14.png b/ios/assets/images/emoji/sg14.png new file mode 100644 index 0000000..c5cc155 Binary files /dev/null and b/ios/assets/images/emoji/sg14.png differ diff --git a/ios/assets/images/emoji/sg143.png b/ios/assets/images/emoji/sg143.png new file mode 100644 index 0000000..6a7ad79 Binary files /dev/null and b/ios/assets/images/emoji/sg143.png differ diff --git a/ios/assets/images/emoji/sg15.png b/ios/assets/images/emoji/sg15.png new file mode 100644 index 0000000..e77a4da Binary files /dev/null and b/ios/assets/images/emoji/sg15.png differ diff --git a/ios/assets/images/emoji/sg153.png b/ios/assets/images/emoji/sg153.png new file mode 100644 index 0000000..f119cd9 Binary files /dev/null and b/ios/assets/images/emoji/sg153.png differ diff --git a/ios/assets/images/emoji/sg16.png b/ios/assets/images/emoji/sg16.png new file mode 100644 index 0000000..845f290 Binary files /dev/null and b/ios/assets/images/emoji/sg16.png differ diff --git a/ios/assets/images/emoji/sg163.png b/ios/assets/images/emoji/sg163.png new file mode 100644 index 0000000..1a3629e Binary files /dev/null and b/ios/assets/images/emoji/sg163.png differ diff --git a/ios/assets/images/emoji/sg164.png b/ios/assets/images/emoji/sg164.png new file mode 100644 index 0000000..90837c5 Binary files /dev/null and b/ios/assets/images/emoji/sg164.png differ diff --git a/ios/assets/images/emoji/sg165.png b/ios/assets/images/emoji/sg165.png new file mode 100644 index 0000000..a4ab65f Binary files /dev/null and b/ios/assets/images/emoji/sg165.png differ diff --git a/ios/assets/images/emoji/sg166.png b/ios/assets/images/emoji/sg166.png new file mode 100644 index 0000000..ddc733e Binary files /dev/null and b/ios/assets/images/emoji/sg166.png differ diff --git a/ios/assets/images/emoji/sg167.png b/ios/assets/images/emoji/sg167.png new file mode 100644 index 0000000..dfdab79 Binary files /dev/null and b/ios/assets/images/emoji/sg167.png differ diff --git a/ios/assets/images/emoji/sg168.png b/ios/assets/images/emoji/sg168.png new file mode 100644 index 0000000..b811200 Binary files /dev/null and b/ios/assets/images/emoji/sg168.png differ diff --git a/ios/assets/images/emoji/sg169.png b/ios/assets/images/emoji/sg169.png new file mode 100644 index 0000000..9e897eb Binary files /dev/null and b/ios/assets/images/emoji/sg169.png differ diff --git a/ios/assets/images/emoji/sg17.png b/ios/assets/images/emoji/sg17.png new file mode 100644 index 0000000..3d5212e Binary files /dev/null and b/ios/assets/images/emoji/sg17.png differ diff --git a/ios/assets/images/emoji/sg170.png b/ios/assets/images/emoji/sg170.png new file mode 100644 index 0000000..fea7b11 Binary files /dev/null and b/ios/assets/images/emoji/sg170.png differ diff --git a/ios/assets/images/emoji/sg171.png b/ios/assets/images/emoji/sg171.png new file mode 100644 index 0000000..190be52 Binary files /dev/null and b/ios/assets/images/emoji/sg171.png differ diff --git a/ios/assets/images/emoji/sg172.png b/ios/assets/images/emoji/sg172.png new file mode 100644 index 0000000..03d27d6 Binary files /dev/null and b/ios/assets/images/emoji/sg172.png differ diff --git a/ios/assets/images/emoji/sg173.png b/ios/assets/images/emoji/sg173.png new file mode 100644 index 0000000..66fbdbf Binary files /dev/null and b/ios/assets/images/emoji/sg173.png differ diff --git a/ios/assets/images/emoji/sg174.png b/ios/assets/images/emoji/sg174.png new file mode 100644 index 0000000..b1badb1 Binary files /dev/null and b/ios/assets/images/emoji/sg174.png differ diff --git a/ios/assets/images/emoji/sg175.png b/ios/assets/images/emoji/sg175.png new file mode 100644 index 0000000..7a8df66 Binary files /dev/null and b/ios/assets/images/emoji/sg175.png differ diff --git a/ios/assets/images/emoji/sg176.png b/ios/assets/images/emoji/sg176.png new file mode 100644 index 0000000..db0e91f Binary files /dev/null and b/ios/assets/images/emoji/sg176.png differ diff --git a/ios/assets/images/emoji/sg177.png b/ios/assets/images/emoji/sg177.png new file mode 100644 index 0000000..71a001f Binary files /dev/null and b/ios/assets/images/emoji/sg177.png differ diff --git a/ios/assets/images/emoji/sg178.png b/ios/assets/images/emoji/sg178.png new file mode 100644 index 0000000..4d2585e Binary files /dev/null and b/ios/assets/images/emoji/sg178.png differ diff --git a/ios/assets/images/emoji/sg179.png b/ios/assets/images/emoji/sg179.png new file mode 100644 index 0000000..7c06653 Binary files /dev/null and b/ios/assets/images/emoji/sg179.png differ diff --git a/ios/assets/images/emoji/sg18.png b/ios/assets/images/emoji/sg18.png new file mode 100644 index 0000000..929f2cf Binary files /dev/null and b/ios/assets/images/emoji/sg18.png differ diff --git a/ios/assets/images/emoji/sg19.png b/ios/assets/images/emoji/sg19.png new file mode 100644 index 0000000..6c911b6 Binary files /dev/null and b/ios/assets/images/emoji/sg19.png differ diff --git a/ios/assets/images/emoji/sg2.png b/ios/assets/images/emoji/sg2.png new file mode 100644 index 0000000..ce32360 Binary files /dev/null and b/ios/assets/images/emoji/sg2.png differ diff --git a/ios/assets/images/emoji/sg20.png b/ios/assets/images/emoji/sg20.png new file mode 100644 index 0000000..ac5f0f7 Binary files /dev/null and b/ios/assets/images/emoji/sg20.png differ diff --git a/ios/assets/images/emoji/sg21.png b/ios/assets/images/emoji/sg21.png new file mode 100644 index 0000000..d25887b Binary files /dev/null and b/ios/assets/images/emoji/sg21.png differ diff --git a/ios/assets/images/emoji/sg22.png b/ios/assets/images/emoji/sg22.png new file mode 100644 index 0000000..3ee4baa Binary files /dev/null and b/ios/assets/images/emoji/sg22.png differ diff --git a/ios/assets/images/emoji/sg23.png b/ios/assets/images/emoji/sg23.png new file mode 100644 index 0000000..8a4fbd4 Binary files /dev/null and b/ios/assets/images/emoji/sg23.png differ diff --git a/ios/assets/images/emoji/sg24.png b/ios/assets/images/emoji/sg24.png new file mode 100644 index 0000000..2c4fc74 Binary files /dev/null and b/ios/assets/images/emoji/sg24.png differ diff --git a/ios/assets/images/emoji/sg25.png b/ios/assets/images/emoji/sg25.png new file mode 100644 index 0000000..2b59402 Binary files /dev/null and b/ios/assets/images/emoji/sg25.png differ diff --git a/ios/assets/images/emoji/sg26.png b/ios/assets/images/emoji/sg26.png new file mode 100644 index 0000000..7fae81d Binary files /dev/null and b/ios/assets/images/emoji/sg26.png differ diff --git a/ios/assets/images/emoji/sg27.png b/ios/assets/images/emoji/sg27.png new file mode 100644 index 0000000..52cdb7a Binary files /dev/null and b/ios/assets/images/emoji/sg27.png differ diff --git a/ios/assets/images/emoji/sg28.png b/ios/assets/images/emoji/sg28.png new file mode 100644 index 0000000..838fec8 Binary files /dev/null and b/ios/assets/images/emoji/sg28.png differ diff --git a/ios/assets/images/emoji/sg29.png b/ios/assets/images/emoji/sg29.png new file mode 100644 index 0000000..688cacf Binary files /dev/null and b/ios/assets/images/emoji/sg29.png differ diff --git a/ios/assets/images/emoji/sg3.png b/ios/assets/images/emoji/sg3.png new file mode 100644 index 0000000..f4758c1 Binary files /dev/null and b/ios/assets/images/emoji/sg3.png differ diff --git a/ios/assets/images/emoji/sg30.png b/ios/assets/images/emoji/sg30.png new file mode 100644 index 0000000..cca17b6 Binary files /dev/null and b/ios/assets/images/emoji/sg30.png differ diff --git a/ios/assets/images/emoji/sg31.png b/ios/assets/images/emoji/sg31.png new file mode 100644 index 0000000..f7a8375 Binary files /dev/null and b/ios/assets/images/emoji/sg31.png differ diff --git a/ios/assets/images/emoji/sg32.png b/ios/assets/images/emoji/sg32.png new file mode 100644 index 0000000..2e1be8c Binary files /dev/null and b/ios/assets/images/emoji/sg32.png differ diff --git a/ios/assets/images/emoji/sg33.png b/ios/assets/images/emoji/sg33.png new file mode 100644 index 0000000..d156106 Binary files /dev/null and b/ios/assets/images/emoji/sg33.png differ diff --git a/ios/assets/images/emoji/sg34.png b/ios/assets/images/emoji/sg34.png new file mode 100644 index 0000000..59ffe75 Binary files /dev/null and b/ios/assets/images/emoji/sg34.png differ diff --git a/ios/assets/images/emoji/sg35.png b/ios/assets/images/emoji/sg35.png new file mode 100644 index 0000000..bfa3c0b Binary files /dev/null and b/ios/assets/images/emoji/sg35.png differ diff --git a/ios/assets/images/emoji/sg36.png b/ios/assets/images/emoji/sg36.png new file mode 100644 index 0000000..519bf88 Binary files /dev/null and b/ios/assets/images/emoji/sg36.png differ diff --git a/ios/assets/images/emoji/sg37.png b/ios/assets/images/emoji/sg37.png new file mode 100644 index 0000000..2dee27b Binary files /dev/null and b/ios/assets/images/emoji/sg37.png differ diff --git a/ios/assets/images/emoji/sg38.png b/ios/assets/images/emoji/sg38.png new file mode 100644 index 0000000..fd4df24 Binary files /dev/null and b/ios/assets/images/emoji/sg38.png differ diff --git a/ios/assets/images/emoji/sg39.png b/ios/assets/images/emoji/sg39.png new file mode 100644 index 0000000..d514d47 Binary files /dev/null and b/ios/assets/images/emoji/sg39.png differ diff --git a/ios/assets/images/emoji/sg4.png b/ios/assets/images/emoji/sg4.png new file mode 100644 index 0000000..36ad693 Binary files /dev/null and b/ios/assets/images/emoji/sg4.png differ diff --git a/ios/assets/images/emoji/sg40.png b/ios/assets/images/emoji/sg40.png new file mode 100644 index 0000000..84778ab Binary files /dev/null and b/ios/assets/images/emoji/sg40.png differ diff --git a/ios/assets/images/emoji/sg41.png b/ios/assets/images/emoji/sg41.png new file mode 100644 index 0000000..dc7eecb Binary files /dev/null and b/ios/assets/images/emoji/sg41.png differ diff --git a/ios/assets/images/emoji/sg42.png b/ios/assets/images/emoji/sg42.png new file mode 100644 index 0000000..ca5ee9a Binary files /dev/null and b/ios/assets/images/emoji/sg42.png differ diff --git a/ios/assets/images/emoji/sg43.png b/ios/assets/images/emoji/sg43.png new file mode 100644 index 0000000..b320132 Binary files /dev/null and b/ios/assets/images/emoji/sg43.png differ diff --git a/ios/assets/images/emoji/sg44.png b/ios/assets/images/emoji/sg44.png new file mode 100644 index 0000000..2d8b68d Binary files /dev/null and b/ios/assets/images/emoji/sg44.png differ diff --git a/ios/assets/images/emoji/sg45.png b/ios/assets/images/emoji/sg45.png new file mode 100644 index 0000000..7b830c7 Binary files /dev/null and b/ios/assets/images/emoji/sg45.png differ diff --git a/ios/assets/images/emoji/sg46.png b/ios/assets/images/emoji/sg46.png new file mode 100644 index 0000000..1f7763b Binary files /dev/null and b/ios/assets/images/emoji/sg46.png differ diff --git a/ios/assets/images/emoji/sg47.png b/ios/assets/images/emoji/sg47.png new file mode 100644 index 0000000..2d99dce Binary files /dev/null and b/ios/assets/images/emoji/sg47.png differ diff --git a/ios/assets/images/emoji/sg48.png b/ios/assets/images/emoji/sg48.png new file mode 100644 index 0000000..e731351 Binary files /dev/null and b/ios/assets/images/emoji/sg48.png differ diff --git a/ios/assets/images/emoji/sg49.png b/ios/assets/images/emoji/sg49.png new file mode 100644 index 0000000..373c918 Binary files /dev/null and b/ios/assets/images/emoji/sg49.png differ diff --git a/ios/assets/images/emoji/sg5.png b/ios/assets/images/emoji/sg5.png new file mode 100644 index 0000000..a0ec7bd Binary files /dev/null and b/ios/assets/images/emoji/sg5.png differ diff --git a/ios/assets/images/emoji/sg50.png b/ios/assets/images/emoji/sg50.png new file mode 100644 index 0000000..f355146 Binary files /dev/null and b/ios/assets/images/emoji/sg50.png differ diff --git a/ios/assets/images/emoji/sg51.png b/ios/assets/images/emoji/sg51.png new file mode 100644 index 0000000..7672f1f Binary files /dev/null and b/ios/assets/images/emoji/sg51.png differ diff --git a/ios/assets/images/emoji/sg52.png b/ios/assets/images/emoji/sg52.png new file mode 100644 index 0000000..c0bfd8e Binary files /dev/null and b/ios/assets/images/emoji/sg52.png differ diff --git a/ios/assets/images/emoji/sg53.png b/ios/assets/images/emoji/sg53.png new file mode 100644 index 0000000..469386f Binary files /dev/null and b/ios/assets/images/emoji/sg53.png differ diff --git a/ios/assets/images/emoji/sg54.png b/ios/assets/images/emoji/sg54.png new file mode 100644 index 0000000..97708c7 Binary files /dev/null and b/ios/assets/images/emoji/sg54.png differ diff --git a/ios/assets/images/emoji/sg55.png b/ios/assets/images/emoji/sg55.png new file mode 100644 index 0000000..6238725 Binary files /dev/null and b/ios/assets/images/emoji/sg55.png differ diff --git a/ios/assets/images/emoji/sg56.png b/ios/assets/images/emoji/sg56.png new file mode 100644 index 0000000..19dc564 Binary files /dev/null and b/ios/assets/images/emoji/sg56.png differ diff --git a/ios/assets/images/emoji/sg57.png b/ios/assets/images/emoji/sg57.png new file mode 100644 index 0000000..2c69738 Binary files /dev/null and b/ios/assets/images/emoji/sg57.png differ diff --git a/ios/assets/images/emoji/sg58.png b/ios/assets/images/emoji/sg58.png new file mode 100644 index 0000000..ad9b0af Binary files /dev/null and b/ios/assets/images/emoji/sg58.png differ diff --git a/ios/assets/images/emoji/sg59.png b/ios/assets/images/emoji/sg59.png new file mode 100644 index 0000000..b1803c3 Binary files /dev/null and b/ios/assets/images/emoji/sg59.png differ diff --git a/ios/assets/images/emoji/sg6.png b/ios/assets/images/emoji/sg6.png new file mode 100644 index 0000000..110e783 Binary files /dev/null and b/ios/assets/images/emoji/sg6.png differ diff --git a/ios/assets/images/emoji/sg60.png b/ios/assets/images/emoji/sg60.png new file mode 100644 index 0000000..1674fc4 Binary files /dev/null and b/ios/assets/images/emoji/sg60.png differ diff --git a/ios/assets/images/emoji/sg61.png b/ios/assets/images/emoji/sg61.png new file mode 100644 index 0000000..bc25c6d Binary files /dev/null and b/ios/assets/images/emoji/sg61.png differ diff --git a/ios/assets/images/emoji/sg62.png b/ios/assets/images/emoji/sg62.png new file mode 100644 index 0000000..d6601f2 Binary files /dev/null and b/ios/assets/images/emoji/sg62.png differ diff --git a/ios/assets/images/emoji/sg63.png b/ios/assets/images/emoji/sg63.png new file mode 100644 index 0000000..b10f8d8 Binary files /dev/null and b/ios/assets/images/emoji/sg63.png differ diff --git a/ios/assets/images/emoji/sg64.png b/ios/assets/images/emoji/sg64.png new file mode 100644 index 0000000..156dd4c Binary files /dev/null and b/ios/assets/images/emoji/sg64.png differ diff --git a/ios/assets/images/emoji/sg65.png b/ios/assets/images/emoji/sg65.png new file mode 100644 index 0000000..60f075c Binary files /dev/null and b/ios/assets/images/emoji/sg65.png differ diff --git a/ios/assets/images/emoji/sg66.png b/ios/assets/images/emoji/sg66.png new file mode 100644 index 0000000..4429d67 Binary files /dev/null and b/ios/assets/images/emoji/sg66.png differ diff --git a/ios/assets/images/emoji/sg67.png b/ios/assets/images/emoji/sg67.png new file mode 100644 index 0000000..38b5cd7 Binary files /dev/null and b/ios/assets/images/emoji/sg67.png differ diff --git a/ios/assets/images/emoji/sg68.png b/ios/assets/images/emoji/sg68.png new file mode 100644 index 0000000..b53e6c2 Binary files /dev/null and b/ios/assets/images/emoji/sg68.png differ diff --git a/ios/assets/images/emoji/sg69.png b/ios/assets/images/emoji/sg69.png new file mode 100644 index 0000000..3437d24 Binary files /dev/null and b/ios/assets/images/emoji/sg69.png differ diff --git a/ios/assets/images/emoji/sg7.png b/ios/assets/images/emoji/sg7.png new file mode 100644 index 0000000..842a9e0 Binary files /dev/null and b/ios/assets/images/emoji/sg7.png differ diff --git a/ios/assets/images/emoji/sg70.png b/ios/assets/images/emoji/sg70.png new file mode 100644 index 0000000..8b73202 Binary files /dev/null and b/ios/assets/images/emoji/sg70.png differ diff --git a/ios/assets/images/emoji/sg71.png b/ios/assets/images/emoji/sg71.png new file mode 100644 index 0000000..399500e Binary files /dev/null and b/ios/assets/images/emoji/sg71.png differ diff --git a/ios/assets/images/emoji/sg72.png b/ios/assets/images/emoji/sg72.png new file mode 100644 index 0000000..5ae9814 Binary files /dev/null and b/ios/assets/images/emoji/sg72.png differ diff --git a/ios/assets/images/emoji/sg73.png b/ios/assets/images/emoji/sg73.png new file mode 100644 index 0000000..9909ea0 Binary files /dev/null and b/ios/assets/images/emoji/sg73.png differ diff --git a/ios/assets/images/emoji/sg74.png b/ios/assets/images/emoji/sg74.png new file mode 100644 index 0000000..75be52e Binary files /dev/null and b/ios/assets/images/emoji/sg74.png differ diff --git a/ios/assets/images/emoji/sg75.png b/ios/assets/images/emoji/sg75.png new file mode 100644 index 0000000..4254a04 Binary files /dev/null and b/ios/assets/images/emoji/sg75.png differ diff --git a/ios/assets/images/emoji/sg76.png b/ios/assets/images/emoji/sg76.png new file mode 100644 index 0000000..4a646df Binary files /dev/null and b/ios/assets/images/emoji/sg76.png differ diff --git a/ios/assets/images/emoji/sg77.png b/ios/assets/images/emoji/sg77.png new file mode 100644 index 0000000..2a6ef8b Binary files /dev/null and b/ios/assets/images/emoji/sg77.png differ diff --git a/ios/assets/images/emoji/sg78.png b/ios/assets/images/emoji/sg78.png new file mode 100644 index 0000000..a9171bd Binary files /dev/null and b/ios/assets/images/emoji/sg78.png differ diff --git a/ios/assets/images/emoji/sg79.png b/ios/assets/images/emoji/sg79.png new file mode 100644 index 0000000..0be82f6 Binary files /dev/null and b/ios/assets/images/emoji/sg79.png differ diff --git a/ios/assets/images/emoji/sg8.png b/ios/assets/images/emoji/sg8.png new file mode 100644 index 0000000..d1f170a Binary files /dev/null and b/ios/assets/images/emoji/sg8.png differ diff --git a/ios/assets/images/emoji/sg80.png b/ios/assets/images/emoji/sg80.png new file mode 100644 index 0000000..0516c75 Binary files /dev/null and b/ios/assets/images/emoji/sg80.png differ diff --git a/ios/assets/images/emoji/sg81.png b/ios/assets/images/emoji/sg81.png new file mode 100644 index 0000000..5c56212 Binary files /dev/null and b/ios/assets/images/emoji/sg81.png differ diff --git a/ios/assets/images/emoji/sg82.png b/ios/assets/images/emoji/sg82.png new file mode 100644 index 0000000..6a7ad79 Binary files /dev/null and b/ios/assets/images/emoji/sg82.png differ diff --git a/ios/assets/images/emoji/sg83.png b/ios/assets/images/emoji/sg83.png new file mode 100644 index 0000000..f119cd9 Binary files /dev/null and b/ios/assets/images/emoji/sg83.png differ diff --git a/ios/assets/images/emoji/sg84.png b/ios/assets/images/emoji/sg84.png new file mode 100644 index 0000000..1a3629e Binary files /dev/null and b/ios/assets/images/emoji/sg84.png differ diff --git a/ios/assets/images/emoji/sg85.png b/ios/assets/images/emoji/sg85.png new file mode 100644 index 0000000..90837c5 Binary files /dev/null and b/ios/assets/images/emoji/sg85.png differ diff --git a/ios/assets/images/emoji/sg86.png b/ios/assets/images/emoji/sg86.png new file mode 100644 index 0000000..a4ab65f Binary files /dev/null and b/ios/assets/images/emoji/sg86.png differ diff --git a/ios/assets/images/emoji/sg87.png b/ios/assets/images/emoji/sg87.png new file mode 100644 index 0000000..ddc733e Binary files /dev/null and b/ios/assets/images/emoji/sg87.png differ diff --git a/ios/assets/images/emoji/sg88.png b/ios/assets/images/emoji/sg88.png new file mode 100644 index 0000000..dfdab79 Binary files /dev/null and b/ios/assets/images/emoji/sg88.png differ diff --git a/ios/assets/images/emoji/sg89.png b/ios/assets/images/emoji/sg89.png new file mode 100644 index 0000000..b811200 Binary files /dev/null and b/ios/assets/images/emoji/sg89.png differ diff --git a/ios/assets/images/emoji/sg9.png b/ios/assets/images/emoji/sg9.png new file mode 100644 index 0000000..22c0c1a Binary files /dev/null and b/ios/assets/images/emoji/sg9.png differ diff --git a/ios/assets/images/emoji/sg90.png b/ios/assets/images/emoji/sg90.png new file mode 100644 index 0000000..9e897eb Binary files /dev/null and b/ios/assets/images/emoji/sg90.png differ diff --git a/ios/assets/images/emoji/sg91.png b/ios/assets/images/emoji/sg91.png new file mode 100644 index 0000000..fea7b11 Binary files /dev/null and b/ios/assets/images/emoji/sg91.png differ diff --git a/ios/assets/images/emoji/sg92.png b/ios/assets/images/emoji/sg92.png new file mode 100644 index 0000000..190be52 Binary files /dev/null and b/ios/assets/images/emoji/sg92.png differ diff --git a/ios/assets/images/emoji/sg93.png b/ios/assets/images/emoji/sg93.png new file mode 100644 index 0000000..03d27d6 Binary files /dev/null and b/ios/assets/images/emoji/sg93.png differ diff --git a/ios/assets/images/emoji/sg94.png b/ios/assets/images/emoji/sg94.png new file mode 100644 index 0000000..66fbdbf Binary files /dev/null and b/ios/assets/images/emoji/sg94.png differ diff --git a/ios/assets/images/emoji/sg95.png b/ios/assets/images/emoji/sg95.png new file mode 100644 index 0000000..b1badb1 Binary files /dev/null and b/ios/assets/images/emoji/sg95.png differ diff --git a/ios/assets/images/emoji/sg96.png b/ios/assets/images/emoji/sg96.png new file mode 100644 index 0000000..7a8df66 Binary files /dev/null and b/ios/assets/images/emoji/sg96.png differ diff --git a/ios/assets/images/emoji/sg97.png b/ios/assets/images/emoji/sg97.png new file mode 100644 index 0000000..db0e91f Binary files /dev/null and b/ios/assets/images/emoji/sg97.png differ diff --git a/ios/assets/images/emoji/sg98.png b/ios/assets/images/emoji/sg98.png new file mode 100644 index 0000000..71a001f Binary files /dev/null and b/ios/assets/images/emoji/sg98.png differ diff --git a/ios/assets/images/emoji/sg99.png b/ios/assets/images/emoji/sg99.png new file mode 100644 index 0000000..4d2585e Binary files /dev/null and b/ios/assets/images/emoji/sg99.png differ diff --git a/ios/assets/images/friends/comment.png b/ios/assets/images/friends/comment.png new file mode 100644 index 0000000..611fd1c Binary files /dev/null and b/ios/assets/images/friends/comment.png differ diff --git a/ios/assets/images/friends/like.png b/ios/assets/images/friends/like.png new file mode 100644 index 0000000..94cc9fd Binary files /dev/null and b/ios/assets/images/friends/like.png differ diff --git a/ios/assets/images/full_image.png b/ios/assets/images/full_image.png new file mode 100644 index 0000000..041d96d Binary files /dev/null and b/ios/assets/images/full_image.png differ diff --git a/ios/assets/images/goup_call_1.png b/ios/assets/images/goup_call_1.png new file mode 100644 index 0000000..94522df Binary files /dev/null and b/ios/assets/images/goup_call_1.png differ diff --git a/ios/assets/images/group/+.png b/ios/assets/images/group/+.png new file mode 100644 index 0000000..2ad6a3a Binary files /dev/null and b/ios/assets/images/group/+.png differ diff --git a/ios/assets/images/group/-.png b/ios/assets/images/group/-.png new file mode 100644 index 0000000..204c982 Binary files /dev/null and b/ios/assets/images/group/-.png differ diff --git a/ios/assets/images/group/group_code.png b/ios/assets/images/group/group_code.png new file mode 100644 index 0000000..f6804cd Binary files /dev/null and b/ios/assets/images/group/group_code.png differ diff --git a/ios/assets/images/group/ic_right.png b/ios/assets/images/group/ic_right.png new file mode 100644 index 0000000..1327226 Binary files /dev/null and b/ios/assets/images/group/ic_right.png differ diff --git a/ios/assets/images/group/local_background_default.png b/ios/assets/images/group/local_background_default.png new file mode 100644 index 0000000..f32cc1a Binary files /dev/null and b/ios/assets/images/group/local_background_default.png differ diff --git a/ios/assets/images/group/local_background_five.webp b/ios/assets/images/group/local_background_five.webp new file mode 100644 index 0000000..d858eb9 Binary files /dev/null and b/ios/assets/images/group/local_background_five.webp differ diff --git a/ios/assets/images/group/local_background_four.webp b/ios/assets/images/group/local_background_four.webp new file mode 100644 index 0000000..9f40e24 Binary files /dev/null and b/ios/assets/images/group/local_background_four.webp differ diff --git a/ios/assets/images/group/local_background_one.webp b/ios/assets/images/group/local_background_one.webp new file mode 100644 index 0000000..4dbb9a5 Binary files /dev/null and b/ios/assets/images/group/local_background_one.webp differ diff --git a/ios/assets/images/group/local_background_three.webp b/ios/assets/images/group/local_background_three.webp new file mode 100644 index 0000000..b90af5c Binary files /dev/null and b/ios/assets/images/group/local_background_three.webp differ diff --git a/ios/assets/images/group/local_background_two.webp b/ios/assets/images/group/local_background_two.webp new file mode 100644 index 0000000..a3f1022 Binary files /dev/null and b/ios/assets/images/group/local_background_two.webp differ diff --git a/ios/assets/images/group_call_face_2.png b/ios/assets/images/group_call_face_2.png new file mode 100644 index 0000000..db91234 Binary files /dev/null and b/ios/assets/images/group_call_face_2.png differ diff --git a/ios/assets/images/group_call_face_3.png b/ios/assets/images/group_call_face_3.png new file mode 100644 index 0000000..6dbe459 Binary files /dev/null and b/ios/assets/images/group_call_face_3.png differ diff --git a/ios/assets/images/group_call_face_small.png b/ios/assets/images/group_call_face_small.png new file mode 100644 index 0000000..ded35ab Binary files /dev/null and b/ios/assets/images/group_call_face_small.png differ diff --git a/ios/assets/images/login/ic_select_have.webp b/ios/assets/images/login/ic_select_have.webp new file mode 100644 index 0000000..314d42b Binary files /dev/null and b/ios/assets/images/login/ic_select_have.webp differ diff --git a/ios/assets/images/login/ic_select_have_grey.webp b/ios/assets/images/login/ic_select_have_grey.webp new file mode 100644 index 0000000..fc2186c Binary files /dev/null and b/ios/assets/images/login/ic_select_have_grey.webp differ diff --git a/ios/assets/images/login/ic_select_no.png b/ios/assets/images/login/ic_select_no.png new file mode 100644 index 0000000..9a41082 Binary files /dev/null and b/ios/assets/images/login/ic_select_no.png differ diff --git a/ios/assets/images/login/select_avatar.webp b/ios/assets/images/login/select_avatar.webp new file mode 100644 index 0000000..184fe0e Binary files /dev/null and b/ios/assets/images/login/select_avatar.webp differ diff --git a/ios/assets/images/mine/addfriend_icon_myqr.png b/ios/assets/images/mine/addfriend_icon_myqr.png new file mode 100644 index 0000000..bec5bc6 Binary files /dev/null and b/ios/assets/images/mine/addfriend_icon_myqr.png differ diff --git a/ios/assets/images/mine/ic_card_package.png b/ios/assets/images/mine/ic_card_package.png new file mode 100644 index 0000000..e478cd1 Binary files /dev/null and b/ios/assets/images/mine/ic_card_package.png differ diff --git a/ios/assets/images/mine/ic_emoji.png b/ios/assets/images/mine/ic_emoji.png new file mode 100644 index 0000000..58cb371 Binary files /dev/null and b/ios/assets/images/mine/ic_emoji.png differ diff --git a/ios/assets/images/mine/ic_pay.png b/ios/assets/images/mine/ic_pay.png new file mode 100644 index 0000000..cfdf544 Binary files /dev/null and b/ios/assets/images/mine/ic_pay.png differ diff --git a/ios/assets/images/mine/ic_setting.png b/ios/assets/images/mine/ic_setting.png new file mode 100644 index 0000000..93ec00b Binary files /dev/null and b/ios/assets/images/mine/ic_setting.png differ diff --git a/ios/assets/images/mine/ic_small_code.png b/ios/assets/images/mine/ic_small_code.png new file mode 100644 index 0000000..db04111 Binary files /dev/null and b/ios/assets/images/mine/ic_small_code.png differ diff --git a/ios/assets/images/mine/ic_wallet.webp b/ios/assets/images/mine/ic_wallet.webp new file mode 100644 index 0000000..8f27d96 Binary files /dev/null and b/ios/assets/images/mine/ic_wallet.webp differ diff --git a/ios/assets/images/wechat/GroupVerify_NewInvitation_Icon@3x.png b/ios/assets/images/wechat/GroupVerify_NewInvitation_Icon@3x.png new file mode 100644 index 0000000..bd0e2e3 Binary files /dev/null and b/ios/assets/images/wechat/GroupVerify_NewInvitation_Icon@3x.png differ diff --git a/ios/assets/images/wechat/MoreMyBankCard@3x.png b/ios/assets/images/wechat/MoreMyBankCard@3x.png new file mode 100644 index 0000000..21a2590 Binary files /dev/null and b/ios/assets/images/wechat/MoreMyBankCard@3x.png differ diff --git a/ios/assets/images/wechat/Plugins_Album@2x.png b/ios/assets/images/wechat/Plugins_Album@2x.png new file mode 100644 index 0000000..b0917f1 Binary files /dev/null and b/ios/assets/images/wechat/Plugins_Album@2x.png differ diff --git a/ios/assets/images/wechat/Plugins_Album_avatar@2x.png b/ios/assets/images/wechat/Plugins_Album_avatar@2x.png new file mode 100644 index 0000000..f59c079 Binary files /dev/null and b/ios/assets/images/wechat/Plugins_Album_avatar@2x.png differ diff --git a/ios/assets/images/wechat/Plugins_FloatBottle_avatar@2x.png b/ios/assets/images/wechat/Plugins_FloatBottle_avatar@2x.png new file mode 100644 index 0000000..497de69 Binary files /dev/null and b/ios/assets/images/wechat/Plugins_FloatBottle_avatar@2x.png differ diff --git a/ios/assets/images/wechat/Plugins_MediaNote_avatar@2x.png b/ios/assets/images/wechat/Plugins_MediaNote_avatar@2x.png new file mode 100644 index 0000000..0b2924a Binary files /dev/null and b/ios/assets/images/wechat/Plugins_MediaNote_avatar@2x.png differ diff --git a/ios/assets/images/wechat/Plugins_Nearby@2x.png b/ios/assets/images/wechat/Plugins_Nearby@2x.png new file mode 100644 index 0000000..a6022c2 Binary files /dev/null and b/ios/assets/images/wechat/Plugins_Nearby@2x.png differ diff --git a/ios/assets/images/wechat/Plugins_Nearby_avatar@2x.png b/ios/assets/images/wechat/Plugins_Nearby_avatar@2x.png new file mode 100644 index 0000000..ed3168d Binary files /dev/null and b/ios/assets/images/wechat/Plugins_Nearby_avatar@2x.png differ diff --git a/ios/assets/images/wechat/Plugins_News@2x.png b/ios/assets/images/wechat/Plugins_News@2x.png new file mode 100644 index 0000000..c24bbc9 Binary files /dev/null and b/ios/assets/images/wechat/Plugins_News@2x.png differ diff --git a/ios/assets/images/wechat/Plugins_News_avatar@2x.png b/ios/assets/images/wechat/Plugins_News_avatar@2x.png new file mode 100644 index 0000000..2054dd8 Binary files /dev/null and b/ios/assets/images/wechat/Plugins_News_avatar@2x.png differ diff --git a/ios/assets/images/wechat/Plugins_Pushmail_avatar@2x.png b/ios/assets/images/wechat/Plugins_Pushmail_avatar@2x.png new file mode 100644 index 0000000..61b73a0 Binary files /dev/null and b/ios/assets/images/wechat/Plugins_Pushmail_avatar@2x.png differ diff --git a/ios/assets/images/wechat/Plugins_QQMail@2x.png b/ios/assets/images/wechat/Plugins_QQMail@2x.png new file mode 100644 index 0000000..fca169d Binary files /dev/null and b/ios/assets/images/wechat/Plugins_QQMail@2x.png differ diff --git a/ios/assets/images/wechat/Plugins_Shake@2x.png b/ios/assets/images/wechat/Plugins_Shake@2x.png new file mode 100644 index 0000000..65486b9 Binary files /dev/null and b/ios/assets/images/wechat/Plugins_Shake@2x.png differ diff --git a/ios/assets/images/wechat/Plugins_Shake_avatar@2x.png b/ios/assets/images/wechat/Plugins_Shake_avatar@2x.png new file mode 100644 index 0000000..119a43f Binary files /dev/null and b/ios/assets/images/wechat/Plugins_Shake_avatar@2x.png differ diff --git a/ios/assets/images/wechat/Plugins_VoiceInput_avatar@2x.png b/ios/assets/images/wechat/Plugins_VoiceInput_avatar@2x.png new file mode 100644 index 0000000..9814bf2 Binary files /dev/null and b/ios/assets/images/wechat/Plugins_VoiceInput_avatar@2x.png differ diff --git a/ios/assets/images/wechat/Plugins_groupsms@2x.png b/ios/assets/images/wechat/Plugins_groupsms@2x.png new file mode 100644 index 0000000..a2cfb6a Binary files /dev/null and b/ios/assets/images/wechat/Plugins_groupsms@2x.png differ diff --git a/ios/assets/images/wechat/Plugins_groupsms_avatar@2x.png b/ios/assets/images/wechat/Plugins_groupsms_avatar@2x.png new file mode 100644 index 0000000..b1be223 Binary files /dev/null and b/ios/assets/images/wechat/Plugins_groupsms_avatar@2x.png differ diff --git a/ios/assets/images/wechat/ProfileLockOff@3x.png b/ios/assets/images/wechat/ProfileLockOff@3x.png new file mode 100644 index 0000000..f2bbf7c Binary files /dev/null and b/ios/assets/images/wechat/ProfileLockOff@3x.png differ diff --git a/ios/assets/images/wechat/ProfileLockOn@2x.png b/ios/assets/images/wechat/ProfileLockOn@2x.png new file mode 100644 index 0000000..d88d391 Binary files /dev/null and b/ios/assets/images/wechat/ProfileLockOn@2x.png differ diff --git a/ios/assets/images/wechat/ProfileLockOn@3x.png b/ios/assets/images/wechat/ProfileLockOn@3x.png new file mode 100644 index 0000000..b88a963 Binary files /dev/null and b/ios/assets/images/wechat/ProfileLockOn@3x.png differ diff --git a/ios/assets/images/wechat/ReadVerified_icon@3x.png b/ios/assets/images/wechat/ReadVerified_icon@3x.png new file mode 100644 index 0000000..ce5b737 Binary files /dev/null and b/ios/assets/images/wechat/ReadVerified_icon@3x.png differ diff --git a/ios/assets/images/wechat/Receive_Icon@3x.png b/ios/assets/images/wechat/Receive_Icon@3x.png new file mode 100644 index 0000000..4fd5342 Binary files /dev/null and b/ios/assets/images/wechat/Receive_Icon@3x.png differ diff --git a/ios/assets/images/wechat/RecordCancel@3x.png b/ios/assets/images/wechat/RecordCancel@3x.png new file mode 100644 index 0000000..2ec6341 Binary files /dev/null and b/ios/assets/images/wechat/RecordCancel@3x.png differ diff --git a/ios/assets/images/wechat/RecordingBkg@3x.png b/ios/assets/images/wechat/RecordingBkg@3x.png new file mode 100644 index 0000000..8140ff7 Binary files /dev/null and b/ios/assets/images/wechat/RecordingBkg@3x.png differ diff --git a/ios/assets/images/wechat/RecordingSignal003@3x.png b/ios/assets/images/wechat/RecordingSignal003@3x.png new file mode 100644 index 0000000..ad2b14e Binary files /dev/null and b/ios/assets/images/wechat/RecordingSignal003@3x.png differ diff --git a/ios/assets/images/wechat/RecordingSignal004@2x.png b/ios/assets/images/wechat/RecordingSignal004@2x.png new file mode 100644 index 0000000..5aa2527 Binary files /dev/null and b/ios/assets/images/wechat/RecordingSignal004@2x.png differ diff --git a/ios/assets/images/wechat/RecordingSignal004@3x.png b/ios/assets/images/wechat/RecordingSignal004@3x.png new file mode 100644 index 0000000..ce4d8bf Binary files /dev/null and b/ios/assets/images/wechat/RecordingSignal004@3x.png differ diff --git a/ios/assets/images/wechat/RecordingSignal005@2x.png b/ios/assets/images/wechat/RecordingSignal005@2x.png new file mode 100644 index 0000000..45d56f2 Binary files /dev/null and b/ios/assets/images/wechat/RecordingSignal005@2x.png differ diff --git a/ios/assets/images/wechat/RecordingSignal005@3x.png b/ios/assets/images/wechat/RecordingSignal005@3x.png new file mode 100644 index 0000000..4fc60e3 Binary files /dev/null and b/ios/assets/images/wechat/RecordingSignal005@3x.png differ diff --git a/ios/assets/images/wechat/RecordingSignal006@2x.png b/ios/assets/images/wechat/RecordingSignal006@2x.png new file mode 100644 index 0000000..9f21139 Binary files /dev/null and b/ios/assets/images/wechat/RecordingSignal006@2x.png differ diff --git a/ios/assets/images/wechat/RecordingSignal006@3x.png b/ios/assets/images/wechat/RecordingSignal006@3x.png new file mode 100644 index 0000000..470dba1 Binary files /dev/null and b/ios/assets/images/wechat/RecordingSignal006@3x.png differ diff --git a/ios/assets/images/wechat/RecordingSignal007@2x.png b/ios/assets/images/wechat/RecordingSignal007@2x.png new file mode 100644 index 0000000..bb9dc28 Binary files /dev/null and b/ios/assets/images/wechat/RecordingSignal007@2x.png differ diff --git a/ios/assets/images/wechat/RecordingSignal007@3x.png b/ios/assets/images/wechat/RecordingSignal007@3x.png new file mode 100644 index 0000000..f18bbe2 Binary files /dev/null and b/ios/assets/images/wechat/RecordingSignal007@3x.png differ diff --git a/ios/assets/images/wechat/RecordingSignal008@2x.png b/ios/assets/images/wechat/RecordingSignal008@2x.png new file mode 100644 index 0000000..bb9dc28 Binary files /dev/null and b/ios/assets/images/wechat/RecordingSignal008@2x.png differ diff --git a/ios/assets/images/wechat/RecordingSignal008@3x.png b/ios/assets/images/wechat/RecordingSignal008@3x.png new file mode 100644 index 0000000..9f73b8d Binary files /dev/null and b/ios/assets/images/wechat/RecordingSignal008@3x.png differ diff --git a/ios/assets/images/wechat/SafetyInsurance@2x.png b/ios/assets/images/wechat/SafetyInsurance@2x.png new file mode 100644 index 0000000..a641e2c Binary files /dev/null and b/ios/assets/images/wechat/SafetyInsurance@2x.png differ diff --git a/ios/assets/images/wechat/SafetyInsurance@3x.png b/ios/assets/images/wechat/SafetyInsurance@3x.png new file mode 100644 index 0000000..3ebd438 Binary files /dev/null and b/ios/assets/images/wechat/SafetyInsurance@3x.png differ diff --git a/ios/assets/images/wechat/ScanBook@3x.png b/ios/assets/images/wechat/ScanBook@3x.png new file mode 100644 index 0000000..7291fa0 Binary files /dev/null and b/ios/assets/images/wechat/ScanBook@3x.png differ diff --git a/ios/assets/images/wechat/ScanBook_HL@3x.png b/ios/assets/images/wechat/ScanBook_HL@3x.png new file mode 100644 index 0000000..2f75dbf Binary files /dev/null and b/ios/assets/images/wechat/ScanBook_HL@3x.png differ diff --git a/ios/assets/images/wechat/ScanQRCode@3x.png b/ios/assets/images/wechat/ScanQRCode@3x.png new file mode 100644 index 0000000..d2505e4 Binary files /dev/null and b/ios/assets/images/wechat/ScanQRCode@3x.png differ diff --git a/ios/assets/images/wechat/ScanQRCodeAction@2x.png b/ios/assets/images/wechat/ScanQRCodeAction@2x.png new file mode 100644 index 0000000..2a67cd1 Binary files /dev/null and b/ios/assets/images/wechat/ScanQRCodeAction@2x.png differ diff --git a/ios/assets/images/wechat/ScanQRCode_HL@3x.png b/ios/assets/images/wechat/ScanQRCode_HL@3x.png new file mode 100644 index 0000000..960bfeb Binary files /dev/null and b/ios/assets/images/wechat/ScanQRCode_HL@3x.png differ diff --git a/ios/assets/images/wechat/ScanStreet@3x.png b/ios/assets/images/wechat/ScanStreet@3x.png new file mode 100644 index 0000000..86cb5e1 Binary files /dev/null and b/ios/assets/images/wechat/ScanStreet@3x.png differ diff --git a/ios/assets/images/wechat/ScanStreet_HL@3x.png b/ios/assets/images/wechat/ScanStreet_HL@3x.png new file mode 100644 index 0000000..ed699b7 Binary files /dev/null and b/ios/assets/images/wechat/ScanStreet_HL@3x.png differ diff --git a/ios/assets/images/wechat/ScanTrans@3x.png b/ios/assets/images/wechat/ScanTrans@3x.png new file mode 100644 index 0000000..f00a1c6 Binary files /dev/null and b/ios/assets/images/wechat/ScanTrans@3x.png differ diff --git a/ios/assets/images/wechat/ScanTrans_HL@3x.png b/ios/assets/images/wechat/ScanTrans_HL@3x.png new file mode 100644 index 0000000..5a7d7e4 Binary files /dev/null and b/ios/assets/images/wechat/ScanTrans_HL@3x.png differ diff --git a/ios/assets/images/wechat/ScanWord@3x.png b/ios/assets/images/wechat/ScanWord@3x.png new file mode 100644 index 0000000..02af3fc Binary files /dev/null and b/ios/assets/images/wechat/ScanWord@3x.png differ diff --git a/ios/assets/images/wechat/ScanWord_HL@3x.png b/ios/assets/images/wechat/ScanWord_HL@3x.png new file mode 100644 index 0000000..790a26a Binary files /dev/null and b/ios/assets/images/wechat/ScanWord_HL@3x.png differ diff --git a/ios/assets/images/wechat/ServiceInform_icon@3x.png b/ios/assets/images/wechat/ServiceInform_icon@3x.png new file mode 100644 index 0000000..ddf1cc4 Binary files /dev/null and b/ios/assets/images/wechat/ServiceInform_icon@3x.png differ diff --git a/ios/assets/images/wechat/SettingProfileHead@2x.png b/ios/assets/images/wechat/SettingProfileHead@2x.png new file mode 100644 index 0000000..8f29c5a Binary files /dev/null and b/ios/assets/images/wechat/SettingProfileHead@2x.png differ diff --git a/ios/assets/images/wechat/Shake_icon_beacon@2x.png b/ios/assets/images/wechat/Shake_icon_beacon@2x.png new file mode 100644 index 0000000..cf54d1f Binary files /dev/null and b/ios/assets/images/wechat/Shake_icon_beacon@2x.png differ diff --git a/ios/assets/images/wechat/Shake_icon_beaconHL@2x.png b/ios/assets/images/wechat/Shake_icon_beaconHL@2x.png new file mode 100644 index 0000000..a1ad2f5 Binary files /dev/null and b/ios/assets/images/wechat/Shake_icon_beaconHL@2x.png differ diff --git a/ios/assets/images/wechat/Shake_icon_cardPack@2x.png b/ios/assets/images/wechat/Shake_icon_cardPack@2x.png new file mode 100644 index 0000000..be623fa Binary files /dev/null and b/ios/assets/images/wechat/Shake_icon_cardPack@2x.png differ diff --git a/ios/assets/images/wechat/Shake_icon_cardPackHL@2x.png b/ios/assets/images/wechat/Shake_icon_cardPackHL@2x.png new file mode 100644 index 0000000..e479b0f Binary files /dev/null and b/ios/assets/images/wechat/Shake_icon_cardPackHL@2x.png differ diff --git a/ios/assets/images/wechat/Shake_icon_music@2x.png b/ios/assets/images/wechat/Shake_icon_music@2x.png new file mode 100644 index 0000000..5be59df Binary files /dev/null and b/ios/assets/images/wechat/Shake_icon_music@2x.png differ diff --git a/ios/assets/images/wechat/Shake_icon_musicHL@2x.png b/ios/assets/images/wechat/Shake_icon_musicHL@2x.png new file mode 100644 index 0000000..d775a92 Binary files /dev/null and b/ios/assets/images/wechat/Shake_icon_musicHL@2x.png differ diff --git a/ios/assets/images/wechat/Shake_icon_people@2x.png b/ios/assets/images/wechat/Shake_icon_people@2x.png new file mode 100644 index 0000000..99a151f Binary files /dev/null and b/ios/assets/images/wechat/Shake_icon_people@2x.png differ diff --git a/ios/assets/images/wechat/Shake_icon_peopleHL@2x.png b/ios/assets/images/wechat/Shake_icon_peopleHL@2x.png new file mode 100644 index 0000000..da85d9a Binary files /dev/null and b/ios/assets/images/wechat/Shake_icon_peopleHL@2x.png differ diff --git a/ios/assets/images/wechat/Shake_icon_tv@2x.png b/ios/assets/images/wechat/Shake_icon_tv@2x.png new file mode 100644 index 0000000..769d3d4 Binary files /dev/null and b/ios/assets/images/wechat/Shake_icon_tv@2x.png differ diff --git a/ios/assets/images/wechat/aau.png b/ios/assets/images/wechat/aau.png new file mode 100644 index 0000000..5ebb7ec Binary files /dev/null and b/ios/assets/images/wechat/aau.png differ diff --git a/ios/assets/images/wechat/aay.png b/ios/assets/images/wechat/aay.png new file mode 100644 index 0000000..7b51f36 Binary files /dev/null and b/ios/assets/images/wechat/aay.png differ diff --git a/ios/assets/images/wechat/ac9.9.png b/ios/assets/images/wechat/ac9.9.png new file mode 100644 index 0000000..3853660 Binary files /dev/null and b/ios/assets/images/wechat/ac9.9.png differ diff --git a/ios/assets/images/wechat/aca.png b/ios/assets/images/wechat/aca.png new file mode 100644 index 0000000..9e5332c Binary files /dev/null and b/ios/assets/images/wechat/aca.png differ diff --git a/ios/assets/images/wechat/acb.png b/ios/assets/images/wechat/acb.png new file mode 100644 index 0000000..7232653 Binary files /dev/null and b/ios/assets/images/wechat/acb.png differ diff --git a/ios/assets/images/wechat/acc.9.png b/ios/assets/images/wechat/acc.9.png new file mode 100644 index 0000000..7b07cbe Binary files /dev/null and b/ios/assets/images/wechat/acc.9.png differ diff --git a/ios/assets/images/wechat/acd.9.png b/ios/assets/images/wechat/acd.9.png new file mode 100644 index 0000000..c004bb4 Binary files /dev/null and b/ios/assets/images/wechat/acd.9.png differ diff --git a/ios/assets/images/wechat/acg.png b/ios/assets/images/wechat/acg.png new file mode 100644 index 0000000..948e246 Binary files /dev/null and b/ios/assets/images/wechat/acg.png differ diff --git a/ios/assets/images/wechat/ach.png b/ios/assets/images/wechat/ach.png new file mode 100644 index 0000000..2754c98 Binary files /dev/null and b/ios/assets/images/wechat/ach.png differ diff --git a/ios/assets/images/wechat/ad0.png b/ios/assets/images/wechat/ad0.png new file mode 100644 index 0000000..af9ffed Binary files /dev/null and b/ios/assets/images/wechat/ad0.png differ diff --git a/ios/assets/images/wechat/ad9.png b/ios/assets/images/wechat/ad9.png new file mode 100644 index 0000000..7dd72c6 Binary files /dev/null and b/ios/assets/images/wechat/ad9.png differ diff --git a/ios/assets/images/wechat/ad_detail_weapp_icon2@3x.png b/ios/assets/images/wechat/ad_detail_weapp_icon2@3x.png new file mode 100644 index 0000000..9829ecc Binary files /dev/null and b/ios/assets/images/wechat/ad_detail_weapp_icon2@3x.png differ diff --git a/ios/assets/images/wechat/ad_detail_weapp_icon@3x.png b/ios/assets/images/wechat/ad_detail_weapp_icon@3x.png new file mode 100644 index 0000000..c2c66f7 Binary files /dev/null and b/ios/assets/images/wechat/ad_detail_weapp_icon@3x.png differ diff --git a/ios/assets/images/wechat/add.png b/ios/assets/images/wechat/add.png new file mode 100644 index 0000000..da0c631 Binary files /dev/null and b/ios/assets/images/wechat/add.png differ diff --git a/ios/assets/images/wechat/add_addressicon@2x.png b/ios/assets/images/wechat/add_addressicon@2x.png new file mode 100644 index 0000000..1d39d97 Binary files /dev/null and b/ios/assets/images/wechat/add_addressicon@2x.png differ diff --git a/ios/assets/images/wechat/add_friend_icon_contacts@3x.png b/ios/assets/images/wechat/add_friend_icon_contacts@3x.png new file mode 100644 index 0000000..f55c670 Binary files /dev/null and b/ios/assets/images/wechat/add_friend_icon_contacts@3x.png differ diff --git a/ios/assets/images/wechat/add_friend_icon_invite@3x.png b/ios/assets/images/wechat/add_friend_icon_invite@3x.png new file mode 100644 index 0000000..2ac00dd Binary files /dev/null and b/ios/assets/images/wechat/add_friend_icon_invite@3x.png differ diff --git a/ios/assets/images/wechat/add_friend_icon_newgroup@3x.png b/ios/assets/images/wechat/add_friend_icon_newgroup@3x.png new file mode 100644 index 0000000..d1542af Binary files /dev/null and b/ios/assets/images/wechat/add_friend_icon_newgroup@3x.png differ diff --git a/ios/assets/images/wechat/add_friend_icon_search@3x.png b/ios/assets/images/wechat/add_friend_icon_search@3x.png new file mode 100644 index 0000000..dbeaca4 Binary files /dev/null and b/ios/assets/images/wechat/add_friend_icon_search@3x.png differ diff --git a/ios/assets/images/wechat/ade.png b/ios/assets/images/wechat/ade.png new file mode 100644 index 0000000..dc41fd3 Binary files /dev/null and b/ios/assets/images/wechat/ade.png differ diff --git a/ios/assets/images/wechat/adf.png b/ios/assets/images/wechat/adf.png new file mode 100644 index 0000000..b697207 Binary files /dev/null and b/ios/assets/images/wechat/adf.png differ diff --git a/ios/assets/images/wechat/adg.png b/ios/assets/images/wechat/adg.png new file mode 100644 index 0000000..9c3ce78 Binary files /dev/null and b/ios/assets/images/wechat/adg.png differ diff --git a/ios/assets/images/wechat/adj.png b/ios/assets/images/wechat/adj.png new file mode 100644 index 0000000..73c70b0 Binary files /dev/null and b/ios/assets/images/wechat/adj.png differ diff --git a/ios/assets/images/wechat/adk.png b/ios/assets/images/wechat/adk.png new file mode 100644 index 0000000..f9776df Binary files /dev/null and b/ios/assets/images/wechat/adk.png differ diff --git a/ios/assets/images/wechat/adm.png b/ios/assets/images/wechat/adm.png new file mode 100644 index 0000000..4d16a6a Binary files /dev/null and b/ios/assets/images/wechat/adm.png differ diff --git a/ios/assets/images/wechat/aej.png b/ios/assets/images/wechat/aej.png new file mode 100644 index 0000000..9f8f6ba Binary files /dev/null and b/ios/assets/images/wechat/aej.png differ diff --git a/ios/assets/images/wechat/aft.png b/ios/assets/images/wechat/aft.png new file mode 100644 index 0000000..a2aadd4 Binary files /dev/null and b/ios/assets/images/wechat/aft.png differ diff --git a/ios/assets/images/wechat/afu.png b/ios/assets/images/wechat/afu.png new file mode 100644 index 0000000..517cfae Binary files /dev/null and b/ios/assets/images/wechat/afu.png differ diff --git a/ios/assets/images/wechat/afv.png b/ios/assets/images/wechat/afv.png new file mode 100644 index 0000000..8b372d5 Binary files /dev/null and b/ios/assets/images/wechat/afv.png differ diff --git a/ios/assets/images/wechat/afw.png b/ios/assets/images/wechat/afw.png new file mode 100644 index 0000000..5fbb898 Binary files /dev/null and b/ios/assets/images/wechat/afw.png differ diff --git a/ios/assets/images/wechat/afx.png b/ios/assets/images/wechat/afx.png new file mode 100644 index 0000000..7f0678c Binary files /dev/null and b/ios/assets/images/wechat/afx.png differ diff --git a/ios/assets/images/wechat/agt.png b/ios/assets/images/wechat/agt.png new file mode 100644 index 0000000..b2b1006 Binary files /dev/null and b/ios/assets/images/wechat/agt.png differ diff --git a/ios/assets/images/wechat/ah6.png b/ios/assets/images/wechat/ah6.png new file mode 100644 index 0000000..811d2e4 Binary files /dev/null and b/ios/assets/images/wechat/ah6.png differ diff --git a/ios/assets/images/wechat/ah7.png b/ios/assets/images/wechat/ah7.png new file mode 100644 index 0000000..883d1ac Binary files /dev/null and b/ios/assets/images/wechat/ah7.png differ diff --git a/ios/assets/images/wechat/ah8.png b/ios/assets/images/wechat/ah8.png new file mode 100644 index 0000000..eb79975 Binary files /dev/null and b/ios/assets/images/wechat/ah8.png differ diff --git a/ios/assets/images/wechat/ah9.9.png b/ios/assets/images/wechat/ah9.9.png new file mode 100644 index 0000000..53f37b9 Binary files /dev/null and b/ios/assets/images/wechat/ah9.9.png differ diff --git a/ios/assets/images/wechat/ah9.png b/ios/assets/images/wechat/ah9.png new file mode 100644 index 0000000..5c2b595 Binary files /dev/null and b/ios/assets/images/wechat/ah9.png differ diff --git a/ios/assets/images/wechat/ah_.9.png b/ios/assets/images/wechat/ah_.9.png new file mode 100644 index 0000000..ba7e9b2 Binary files /dev/null and b/ios/assets/images/wechat/ah_.9.png differ diff --git a/ios/assets/images/wechat/aha.png b/ios/assets/images/wechat/aha.png new file mode 100644 index 0000000..d91e698 Binary files /dev/null and b/ios/assets/images/wechat/aha.png differ diff --git a/ios/assets/images/wechat/ahb.png b/ios/assets/images/wechat/ahb.png new file mode 100644 index 0000000..d3ab562 Binary files /dev/null and b/ios/assets/images/wechat/ahb.png differ diff --git a/ios/assets/images/wechat/ahc.png b/ios/assets/images/wechat/ahc.png new file mode 100644 index 0000000..c540c1e Binary files /dev/null and b/ios/assets/images/wechat/ahc.png differ diff --git a/ios/assets/images/wechat/ahd.png b/ios/assets/images/wechat/ahd.png new file mode 100644 index 0000000..85b6fa5 Binary files /dev/null and b/ios/assets/images/wechat/ahd.png differ diff --git a/ios/assets/images/wechat/ahf.png b/ios/assets/images/wechat/ahf.png new file mode 100644 index 0000000..4702f71 Binary files /dev/null and b/ios/assets/images/wechat/ahf.png differ diff --git a/ios/assets/images/wechat/ahg.png b/ios/assets/images/wechat/ahg.png new file mode 100644 index 0000000..58eda8c Binary files /dev/null and b/ios/assets/images/wechat/ahg.png differ diff --git a/ios/assets/images/wechat/aht.png b/ios/assets/images/wechat/aht.png new file mode 100644 index 0000000..d1d4d11 Binary files /dev/null and b/ios/assets/images/wechat/aht.png differ diff --git a/ios/assets/images/wechat/ahu.png b/ios/assets/images/wechat/ahu.png new file mode 100644 index 0000000..67aed98 Binary files /dev/null and b/ios/assets/images/wechat/ahu.png differ diff --git a/ios/assets/images/wechat/ahw.png b/ios/assets/images/wechat/ahw.png new file mode 100644 index 0000000..176f79a Binary files /dev/null and b/ios/assets/images/wechat/ahw.png differ diff --git a/ios/assets/images/wechat/alf.png b/ios/assets/images/wechat/alf.png new file mode 100644 index 0000000..36190c4 Binary files /dev/null and b/ios/assets/images/wechat/alf.png differ diff --git a/ios/assets/images/wechat/alg.png b/ios/assets/images/wechat/alg.png new file mode 100644 index 0000000..c83cad3 Binary files /dev/null and b/ios/assets/images/wechat/alg.png differ diff --git a/ios/assets/images/wechat/alh.png b/ios/assets/images/wechat/alh.png new file mode 100644 index 0000000..d6fb0fd Binary files /dev/null and b/ios/assets/images/wechat/alh.png differ diff --git a/ios/assets/images/wechat/ali.png b/ios/assets/images/wechat/ali.png new file mode 100644 index 0000000..356aea7 Binary files /dev/null and b/ios/assets/images/wechat/ali.png differ diff --git a/ios/assets/images/wechat/alp.png b/ios/assets/images/wechat/alp.png new file mode 100644 index 0000000..9bd9fb4 Binary files /dev/null and b/ios/assets/images/wechat/alp.png differ diff --git a/ios/assets/images/wechat/alq.png b/ios/assets/images/wechat/alq.png new file mode 100644 index 0000000..fe760a2 Binary files /dev/null and b/ios/assets/images/wechat/alq.png differ diff --git a/ios/assets/images/wechat/an4.png b/ios/assets/images/wechat/an4.png new file mode 100644 index 0000000..46d5719 Binary files /dev/null and b/ios/assets/images/wechat/an4.png differ diff --git a/ios/assets/images/wechat/an5.png b/ios/assets/images/wechat/an5.png new file mode 100644 index 0000000..66ac90b Binary files /dev/null and b/ios/assets/images/wechat/an5.png differ diff --git a/ios/assets/images/wechat/an7.png b/ios/assets/images/wechat/an7.png new file mode 100644 index 0000000..87e34d7 Binary files /dev/null and b/ios/assets/images/wechat/an7.png differ diff --git a/ios/assets/images/wechat/an8.png b/ios/assets/images/wechat/an8.png new file mode 100644 index 0000000..f8f3dfe Binary files /dev/null and b/ios/assets/images/wechat/an8.png differ diff --git a/ios/assets/images/wechat/an9.png b/ios/assets/images/wechat/an9.png new file mode 100644 index 0000000..5fe808e Binary files /dev/null and b/ios/assets/images/wechat/an9.png differ diff --git a/ios/assets/images/wechat/an_.png b/ios/assets/images/wechat/an_.png new file mode 100644 index 0000000..9eba6f3 Binary files /dev/null and b/ios/assets/images/wechat/an_.png differ diff --git a/ios/assets/images/wechat/ana.png b/ios/assets/images/wechat/ana.png new file mode 100644 index 0000000..6f01c9e Binary files /dev/null and b/ios/assets/images/wechat/ana.png differ diff --git a/ios/assets/images/wechat/anb.png b/ios/assets/images/wechat/anb.png new file mode 100644 index 0000000..92e58e7 Binary files /dev/null and b/ios/assets/images/wechat/anb.png differ diff --git a/ios/assets/images/wechat/ani.png b/ios/assets/images/wechat/ani.png new file mode 100644 index 0000000..6d62538 Binary files /dev/null and b/ios/assets/images/wechat/ani.png differ diff --git a/ios/assets/images/wechat/anj.png b/ios/assets/images/wechat/anj.png new file mode 100644 index 0000000..1d186a4 Binary files /dev/null and b/ios/assets/images/wechat/anj.png differ diff --git a/ios/assets/images/wechat/anl.png b/ios/assets/images/wechat/anl.png new file mode 100644 index 0000000..60a05bc Binary files /dev/null and b/ios/assets/images/wechat/anl.png differ diff --git a/ios/assets/images/wechat/anm.png b/ios/assets/images/wechat/anm.png new file mode 100644 index 0000000..d781556 Binary files /dev/null and b/ios/assets/images/wechat/anm.png differ diff --git a/ios/assets/images/wechat/aov.png b/ios/assets/images/wechat/aov.png new file mode 100644 index 0000000..a6f0037 Binary files /dev/null and b/ios/assets/images/wechat/aov.png differ diff --git a/ios/assets/images/wechat/ap4.png b/ios/assets/images/wechat/ap4.png new file mode 100644 index 0000000..5bd5d5f Binary files /dev/null and b/ios/assets/images/wechat/ap4.png differ diff --git a/ios/assets/images/wechat/ap5.png b/ios/assets/images/wechat/ap5.png new file mode 100644 index 0000000..f262bf5 Binary files /dev/null and b/ios/assets/images/wechat/ap5.png differ diff --git a/ios/assets/images/wechat/ap6.png b/ios/assets/images/wechat/ap6.png new file mode 100644 index 0000000..3a0e916 Binary files /dev/null and b/ios/assets/images/wechat/ap6.png differ diff --git a/ios/assets/images/wechat/ap7.png b/ios/assets/images/wechat/ap7.png new file mode 100644 index 0000000..7e05660 Binary files /dev/null and b/ios/assets/images/wechat/ap7.png differ diff --git a/ios/assets/images/wechat/ap8.png b/ios/assets/images/wechat/ap8.png new file mode 100644 index 0000000..167a3af Binary files /dev/null and b/ios/assets/images/wechat/ap8.png differ diff --git a/ios/assets/images/wechat/ap9.png b/ios/assets/images/wechat/ap9.png new file mode 100644 index 0000000..302f5d1 Binary files /dev/null and b/ios/assets/images/wechat/ap9.png differ diff --git a/ios/assets/images/wechat/apc.png b/ios/assets/images/wechat/apc.png new file mode 100644 index 0000000..7e7f537 Binary files /dev/null and b/ios/assets/images/wechat/apc.png differ diff --git a/ios/assets/images/wechat/apd.png b/ios/assets/images/wechat/apd.png new file mode 100644 index 0000000..d4d1fcc Binary files /dev/null and b/ios/assets/images/wechat/apd.png differ diff --git a/ios/assets/images/wechat/ape.png b/ios/assets/images/wechat/ape.png new file mode 100644 index 0000000..647179e Binary files /dev/null and b/ios/assets/images/wechat/ape.png differ diff --git a/ios/assets/images/wechat/apf.png b/ios/assets/images/wechat/apf.png new file mode 100644 index 0000000..d16a8b7 Binary files /dev/null and b/ios/assets/images/wechat/apf.png differ diff --git a/ios/assets/images/wechat/apg.png b/ios/assets/images/wechat/apg.png new file mode 100644 index 0000000..24a46c1 Binary files /dev/null and b/ios/assets/images/wechat/apg.png differ diff --git a/ios/assets/images/wechat/aph.png b/ios/assets/images/wechat/aph.png new file mode 100644 index 0000000..8bcc1ae Binary files /dev/null and b/ios/assets/images/wechat/aph.png differ diff --git a/ios/assets/images/wechat/apj.png b/ios/assets/images/wechat/apj.png new file mode 100644 index 0000000..dca0317 Binary files /dev/null and b/ios/assets/images/wechat/apj.png differ diff --git a/ios/assets/images/wechat/apk.png b/ios/assets/images/wechat/apk.png new file mode 100644 index 0000000..1477648 Binary files /dev/null and b/ios/assets/images/wechat/apk.png differ diff --git a/ios/assets/images/wechat/apo.png b/ios/assets/images/wechat/apo.png new file mode 100644 index 0000000..378594e Binary files /dev/null and b/ios/assets/images/wechat/apo.png differ diff --git a/ios/assets/images/wechat/app.png b/ios/assets/images/wechat/app.png new file mode 100644 index 0000000..bccf2d1 Binary files /dev/null and b/ios/assets/images/wechat/app.png differ diff --git a/ios/assets/images/wechat/apt.png b/ios/assets/images/wechat/apt.png new file mode 100644 index 0000000..ffe38a5 Binary files /dev/null and b/ios/assets/images/wechat/apt.png differ diff --git a/ios/assets/images/wechat/apu.png b/ios/assets/images/wechat/apu.png new file mode 100644 index 0000000..49ef78c Binary files /dev/null and b/ios/assets/images/wechat/apu.png differ diff --git a/ios/assets/images/wechat/apv.png b/ios/assets/images/wechat/apv.png new file mode 100644 index 0000000..c5bda2f Binary files /dev/null and b/ios/assets/images/wechat/apv.png differ diff --git a/ios/assets/images/wechat/apw.png b/ios/assets/images/wechat/apw.png new file mode 100644 index 0000000..53737ca Binary files /dev/null and b/ios/assets/images/wechat/apw.png differ diff --git a/ios/assets/images/wechat/apx.png b/ios/assets/images/wechat/apx.png new file mode 100644 index 0000000..8f51f36 Binary files /dev/null and b/ios/assets/images/wechat/apx.png differ diff --git a/ios/assets/images/wechat/apy.png b/ios/assets/images/wechat/apy.png new file mode 100644 index 0000000..b064c9e Binary files /dev/null and b/ios/assets/images/wechat/apy.png differ diff --git a/ios/assets/images/wechat/apz.png b/ios/assets/images/wechat/apz.png new file mode 100644 index 0000000..e37ec1f Binary files /dev/null and b/ios/assets/images/wechat/apz.png differ diff --git a/ios/assets/images/wechat/aq2.png b/ios/assets/images/wechat/aq2.png new file mode 100644 index 0000000..84ba179 Binary files /dev/null and b/ios/assets/images/wechat/aq2.png differ diff --git a/ios/assets/images/wechat/arc.png b/ios/assets/images/wechat/arc.png new file mode 100644 index 0000000..35bf328 Binary files /dev/null and b/ios/assets/images/wechat/arc.png differ diff --git a/ios/assets/images/wechat/arr.png b/ios/assets/images/wechat/arr.png new file mode 100644 index 0000000..b5f3eff Binary files /dev/null and b/ios/assets/images/wechat/arr.png differ diff --git a/ios/assets/images/wechat/arx.png b/ios/assets/images/wechat/arx.png new file mode 100644 index 0000000..1aadfbc Binary files /dev/null and b/ios/assets/images/wechat/arx.png differ diff --git a/ios/assets/images/wechat/asg.png b/ios/assets/images/wechat/asg.png new file mode 100644 index 0000000..974f513 Binary files /dev/null and b/ios/assets/images/wechat/asg.png differ diff --git a/ios/assets/images/wechat/ass.png b/ios/assets/images/wechat/ass.png new file mode 100644 index 0000000..2125668 Binary files /dev/null and b/ios/assets/images/wechat/ass.png differ diff --git a/ios/assets/images/wechat/av2.png b/ios/assets/images/wechat/av2.png new file mode 100644 index 0000000..e347dc4 Binary files /dev/null and b/ios/assets/images/wechat/av2.png differ diff --git a/ios/assets/images/wechat/axv.png b/ios/assets/images/wechat/axv.png new file mode 100644 index 0000000..4080c03 Binary files /dev/null and b/ios/assets/images/wechat/axv.png differ diff --git a/ios/assets/images/wechat/ay0.png b/ios/assets/images/wechat/ay0.png new file mode 100644 index 0000000..8c8072f Binary files /dev/null and b/ios/assets/images/wechat/ay0.png differ diff --git a/ios/assets/images/wechat/b07.png b/ios/assets/images/wechat/b07.png new file mode 100644 index 0000000..2f2b180 Binary files /dev/null and b/ios/assets/images/wechat/b07.png differ diff --git a/ios/assets/images/wechat/b08.png b/ios/assets/images/wechat/b08.png new file mode 100644 index 0000000..4f1f18e Binary files /dev/null and b/ios/assets/images/wechat/b08.png differ diff --git a/ios/assets/images/wechat/b09.png b/ios/assets/images/wechat/b09.png new file mode 100644 index 0000000..23083c3 Binary files /dev/null and b/ios/assets/images/wechat/b09.png differ diff --git a/ios/assets/images/wechat/b0_.png b/ios/assets/images/wechat/b0_.png new file mode 100644 index 0000000..4ef521c Binary files /dev/null and b/ios/assets/images/wechat/b0_.png differ diff --git a/ios/assets/images/wechat/b0b.png b/ios/assets/images/wechat/b0b.png new file mode 100644 index 0000000..8b81ac6 Binary files /dev/null and b/ios/assets/images/wechat/b0b.png differ diff --git a/ios/assets/images/wechat/b0d.png b/ios/assets/images/wechat/b0d.png new file mode 100644 index 0000000..20a8c57 Binary files /dev/null and b/ios/assets/images/wechat/b0d.png differ diff --git a/ios/assets/images/wechat/b0h.png b/ios/assets/images/wechat/b0h.png new file mode 100644 index 0000000..9ce06ce Binary files /dev/null and b/ios/assets/images/wechat/b0h.png differ diff --git a/ios/assets/images/wechat/b15.png b/ios/assets/images/wechat/b15.png new file mode 100644 index 0000000..982d94d Binary files /dev/null and b/ios/assets/images/wechat/b15.png differ diff --git a/ios/assets/images/wechat/b16.png b/ios/assets/images/wechat/b16.png new file mode 100644 index 0000000..de4f57c Binary files /dev/null and b/ios/assets/images/wechat/b16.png differ diff --git a/ios/assets/images/wechat/b18.png b/ios/assets/images/wechat/b18.png new file mode 100644 index 0000000..1c5d99c Binary files /dev/null and b/ios/assets/images/wechat/b18.png differ diff --git a/ios/assets/images/wechat/b1_.png b/ios/assets/images/wechat/b1_.png new file mode 100644 index 0000000..5c4f263 Binary files /dev/null and b/ios/assets/images/wechat/b1_.png differ diff --git a/ios/assets/images/wechat/b1b.png b/ios/assets/images/wechat/b1b.png new file mode 100644 index 0000000..838bb78 Binary files /dev/null and b/ios/assets/images/wechat/b1b.png differ diff --git a/ios/assets/images/wechat/b1d.png b/ios/assets/images/wechat/b1d.png new file mode 100644 index 0000000..3f8718a Binary files /dev/null and b/ios/assets/images/wechat/b1d.png differ diff --git a/ios/assets/images/wechat/b1e.png b/ios/assets/images/wechat/b1e.png new file mode 100644 index 0000000..29f99e2 Binary files /dev/null and b/ios/assets/images/wechat/b1e.png differ diff --git a/ios/assets/images/wechat/b1f.png b/ios/assets/images/wechat/b1f.png new file mode 100644 index 0000000..981080a Binary files /dev/null and b/ios/assets/images/wechat/b1f.png differ diff --git a/ios/assets/images/wechat/b1j.png b/ios/assets/images/wechat/b1j.png new file mode 100644 index 0000000..a8d8f00 Binary files /dev/null and b/ios/assets/images/wechat/b1j.png differ diff --git a/ios/assets/images/wechat/b1l.png b/ios/assets/images/wechat/b1l.png new file mode 100644 index 0000000..510ce80 Binary files /dev/null and b/ios/assets/images/wechat/b1l.png differ diff --git a/ios/assets/images/wechat/b1m.png b/ios/assets/images/wechat/b1m.png new file mode 100644 index 0000000..03573c3 Binary files /dev/null and b/ios/assets/images/wechat/b1m.png differ diff --git a/ios/assets/images/wechat/b2h.png b/ios/assets/images/wechat/b2h.png new file mode 100644 index 0000000..391bc67 Binary files /dev/null and b/ios/assets/images/wechat/b2h.png differ diff --git a/ios/assets/images/wechat/b3b.png b/ios/assets/images/wechat/b3b.png new file mode 100644 index 0000000..58407fc Binary files /dev/null and b/ios/assets/images/wechat/b3b.png differ diff --git a/ios/assets/images/wechat/b3c.png b/ios/assets/images/wechat/b3c.png new file mode 100644 index 0000000..391bc67 Binary files /dev/null and b/ios/assets/images/wechat/b3c.png differ diff --git a/ios/assets/images/wechat/b3e.png b/ios/assets/images/wechat/b3e.png new file mode 100644 index 0000000..9d13454 Binary files /dev/null and b/ios/assets/images/wechat/b3e.png differ diff --git a/ios/assets/images/wechat/b3i.png b/ios/assets/images/wechat/b3i.png new file mode 100644 index 0000000..6e37878 Binary files /dev/null and b/ios/assets/images/wechat/b3i.png differ diff --git a/ios/assets/images/wechat/b3k.png b/ios/assets/images/wechat/b3k.png new file mode 100644 index 0000000..c5a2965 Binary files /dev/null and b/ios/assets/images/wechat/b3k.png differ diff --git a/ios/assets/images/wechat/b3n.png b/ios/assets/images/wechat/b3n.png new file mode 100644 index 0000000..78cb6ce Binary files /dev/null and b/ios/assets/images/wechat/b3n.png differ diff --git a/ios/assets/images/wechat/b4_.png b/ios/assets/images/wechat/b4_.png new file mode 100644 index 0000000..e9d771d Binary files /dev/null and b/ios/assets/images/wechat/b4_.png differ diff --git a/ios/assets/images/wechat/b87.png b/ios/assets/images/wechat/b87.png new file mode 100644 index 0000000..6df9101 Binary files /dev/null and b/ios/assets/images/wechat/b87.png differ diff --git a/ios/assets/images/wechat/b88.png b/ios/assets/images/wechat/b88.png new file mode 100644 index 0000000..2771e92 Binary files /dev/null and b/ios/assets/images/wechat/b88.png differ diff --git a/ios/assets/images/wechat/b8v.png b/ios/assets/images/wechat/b8v.png new file mode 100644 index 0000000..de46b86 Binary files /dev/null and b/ios/assets/images/wechat/b8v.png differ diff --git a/ios/assets/images/wechat/bankcard@3x.png b/ios/assets/images/wechat/bankcard@3x.png new file mode 100644 index 0000000..311cde1 Binary files /dev/null and b/ios/assets/images/wechat/bankcard@3x.png differ diff --git a/ios/assets/images/wechat/barbuttonicon_Camera@3x.png b/ios/assets/images/wechat/barbuttonicon_Camera@3x.png new file mode 100644 index 0000000..d85f3e8 Binary files /dev/null and b/ios/assets/images/wechat/barbuttonicon_Camera@3x.png differ diff --git a/ios/assets/images/wechat/barbuttonicon_InfoSingle@2x.png b/ios/assets/images/wechat/barbuttonicon_InfoSingle@2x.png new file mode 100644 index 0000000..4768c89 Binary files /dev/null and b/ios/assets/images/wechat/barbuttonicon_InfoSingle@2x.png differ diff --git a/ios/assets/images/wechat/barbuttonicon_add@3x.png b/ios/assets/images/wechat/barbuttonicon_add@3x.png new file mode 100644 index 0000000..acb7cc7 Binary files /dev/null and b/ios/assets/images/wechat/barbuttonicon_add@3x.png differ diff --git a/ios/assets/images/wechat/barbuttonicon_addfriends@3x.png b/ios/assets/images/wechat/barbuttonicon_addfriends@3x.png new file mode 100644 index 0000000..6175b3f Binary files /dev/null and b/ios/assets/images/wechat/barbuttonicon_addfriends@3x.png differ diff --git a/ios/assets/images/wechat/barbuttonicon_call@3x.png b/ios/assets/images/wechat/barbuttonicon_call@3x.png new file mode 100644 index 0000000..5a2355c Binary files /dev/null and b/ios/assets/images/wechat/barbuttonicon_call@3x.png differ diff --git a/ios/assets/images/wechat/barbuttonicon_mini_cube@3x.png b/ios/assets/images/wechat/barbuttonicon_mini_cube@3x.png new file mode 100644 index 0000000..4f2fd47 Binary files /dev/null and b/ios/assets/images/wechat/barbuttonicon_mini_cube@3x.png differ diff --git a/ios/assets/images/wechat/barbuttonicon_question@3x.png b/ios/assets/images/wechat/barbuttonicon_question@3x.png new file mode 100644 index 0000000..45369e8 Binary files /dev/null and b/ios/assets/images/wechat/barbuttonicon_question@3x.png differ diff --git a/ios/assets/images/wechat/barbuttonicon_set@3x.png b/ios/assets/images/wechat/barbuttonicon_set@3x.png new file mode 100644 index 0000000..3d36e34 Binary files /dev/null and b/ios/assets/images/wechat/barbuttonicon_set@3x.png differ diff --git a/ios/assets/images/wechat/bi_.png b/ios/assets/images/wechat/bi_.png new file mode 100644 index 0000000..80fa8f4 Binary files /dev/null and b/ios/assets/images/wechat/bi_.png differ diff --git a/ios/assets/images/wechat/bia.png b/ios/assets/images/wechat/bia.png new file mode 100644 index 0000000..17e8405 Binary files /dev/null and b/ios/assets/images/wechat/bia.png differ diff --git a/ios/assets/images/wechat/blb.png b/ios/assets/images/wechat/blb.png new file mode 100644 index 0000000..d6e5f88 Binary files /dev/null and b/ios/assets/images/wechat/blb.png differ diff --git a/ios/assets/images/wechat/blc.png b/ios/assets/images/wechat/blc.png new file mode 100644 index 0000000..82b1ffd Binary files /dev/null and b/ios/assets/images/wechat/blc.png differ diff --git a/ios/assets/images/wechat/bld.png b/ios/assets/images/wechat/bld.png new file mode 100644 index 0000000..66bdc88 Binary files /dev/null and b/ios/assets/images/wechat/bld.png differ diff --git a/ios/assets/images/wechat/bow.png b/ios/assets/images/wechat/bow.png new file mode 100644 index 0000000..df67cee Binary files /dev/null and b/ios/assets/images/wechat/bow.png differ diff --git a/ios/assets/images/wechat/box.png b/ios/assets/images/wechat/box.png new file mode 100644 index 0000000..f8d528d Binary files /dev/null and b/ios/assets/images/wechat/box.png differ diff --git a/ios/assets/images/wechat/boy.png b/ios/assets/images/wechat/boy.png new file mode 100644 index 0000000..a200269 Binary files /dev/null and b/ios/assets/images/wechat/boy.png differ diff --git a/ios/assets/images/wechat/bpd.png b/ios/assets/images/wechat/bpd.png new file mode 100644 index 0000000..0cf2ab9 Binary files /dev/null and b/ios/assets/images/wechat/bpd.png differ diff --git a/ios/assets/images/wechat/bpg.png b/ios/assets/images/wechat/bpg.png new file mode 100644 index 0000000..5bd5d5f Binary files /dev/null and b/ios/assets/images/wechat/bpg.png differ diff --git a/ios/assets/images/wechat/bph.png b/ios/assets/images/wechat/bph.png new file mode 100644 index 0000000..f262bf5 Binary files /dev/null and b/ios/assets/images/wechat/bph.png differ diff --git a/ios/assets/images/wechat/bpi.png b/ios/assets/images/wechat/bpi.png new file mode 100644 index 0000000..3a0e916 Binary files /dev/null and b/ios/assets/images/wechat/bpi.png differ diff --git a/ios/assets/images/wechat/bpj.png b/ios/assets/images/wechat/bpj.png new file mode 100644 index 0000000..7e05660 Binary files /dev/null and b/ios/assets/images/wechat/bpj.png differ diff --git a/ios/assets/images/wechat/bpm.png b/ios/assets/images/wechat/bpm.png new file mode 100644 index 0000000..1fa1f65 Binary files /dev/null and b/ios/assets/images/wechat/bpm.png differ diff --git a/ios/assets/images/wechat/bpn.png b/ios/assets/images/wechat/bpn.png new file mode 100644 index 0000000..4d5d0f5 Binary files /dev/null and b/ios/assets/images/wechat/bpn.png differ diff --git a/ios/assets/images/wechat/bpp.png b/ios/assets/images/wechat/bpp.png new file mode 100644 index 0000000..7e7f537 Binary files /dev/null and b/ios/assets/images/wechat/bpp.png differ diff --git a/ios/assets/images/wechat/bpq.png b/ios/assets/images/wechat/bpq.png new file mode 100644 index 0000000..d4d1fcc Binary files /dev/null and b/ios/assets/images/wechat/bpq.png differ diff --git a/ios/assets/images/wechat/bpr.png b/ios/assets/images/wechat/bpr.png new file mode 100644 index 0000000..647179e Binary files /dev/null and b/ios/assets/images/wechat/bpr.png differ diff --git a/ios/assets/images/wechat/bps.png b/ios/assets/images/wechat/bps.png new file mode 100644 index 0000000..d16a8b7 Binary files /dev/null and b/ios/assets/images/wechat/bps.png differ diff --git a/ios/assets/images/wechat/bpt.png b/ios/assets/images/wechat/bpt.png new file mode 100644 index 0000000..24a46c1 Binary files /dev/null and b/ios/assets/images/wechat/bpt.png differ diff --git a/ios/assets/images/wechat/bpv.png b/ios/assets/images/wechat/bpv.png new file mode 100644 index 0000000..8bcc1ae Binary files /dev/null and b/ios/assets/images/wechat/bpv.png differ diff --git a/ios/assets/images/wechat/bpz.png b/ios/assets/images/wechat/bpz.png new file mode 100644 index 0000000..d4d2247 Binary files /dev/null and b/ios/assets/images/wechat/bpz.png differ diff --git a/ios/assets/images/wechat/bq0.png b/ios/assets/images/wechat/bq0.png new file mode 100644 index 0000000..c6d1fca Binary files /dev/null and b/ios/assets/images/wechat/bq0.png differ diff --git a/ios/assets/images/wechat/bq2.png b/ios/assets/images/wechat/bq2.png new file mode 100644 index 0000000..dca0317 Binary files /dev/null and b/ios/assets/images/wechat/bq2.png differ diff --git a/ios/assets/images/wechat/bq3.png b/ios/assets/images/wechat/bq3.png new file mode 100644 index 0000000..1477648 Binary files /dev/null and b/ios/assets/images/wechat/bq3.png differ diff --git a/ios/assets/images/wechat/bq4.png b/ios/assets/images/wechat/bq4.png new file mode 100644 index 0000000..2f33d8f Binary files /dev/null and b/ios/assets/images/wechat/bq4.png differ diff --git a/ios/assets/images/wechat/bq7.png b/ios/assets/images/wechat/bq7.png new file mode 100644 index 0000000..378594e Binary files /dev/null and b/ios/assets/images/wechat/bq7.png differ diff --git a/ios/assets/images/wechat/bq8.png b/ios/assets/images/wechat/bq8.png new file mode 100644 index 0000000..bccf2d1 Binary files /dev/null and b/ios/assets/images/wechat/bq8.png differ diff --git a/ios/assets/images/wechat/bqb.png b/ios/assets/images/wechat/bqb.png new file mode 100644 index 0000000..ffe38a5 Binary files /dev/null and b/ios/assets/images/wechat/bqb.png differ diff --git a/ios/assets/images/wechat/bqc.png b/ios/assets/images/wechat/bqc.png new file mode 100644 index 0000000..49ef78c Binary files /dev/null and b/ios/assets/images/wechat/bqc.png differ diff --git a/ios/assets/images/wechat/bqd.png b/ios/assets/images/wechat/bqd.png new file mode 100644 index 0000000..c5bda2f Binary files /dev/null and b/ios/assets/images/wechat/bqd.png differ diff --git a/ios/assets/images/wechat/bqi.png b/ios/assets/images/wechat/bqi.png new file mode 100644 index 0000000..b064c9e Binary files /dev/null and b/ios/assets/images/wechat/bqi.png differ diff --git a/ios/assets/images/wechat/bqk.png b/ios/assets/images/wechat/bqk.png new file mode 100644 index 0000000..e37ec1f Binary files /dev/null and b/ios/assets/images/wechat/bqk.png differ diff --git a/ios/assets/images/wechat/c2c_cancle_icon@3x.png b/ios/assets/images/wechat/c2c_cancle_icon@3x.png new file mode 100644 index 0000000..7e508e5 Binary files /dev/null and b/ios/assets/images/wechat/c2c_cancle_icon@3x.png differ diff --git a/ios/assets/images/wechat/c2c_hongbao_icon_hk.png b/ios/assets/images/wechat/c2c_hongbao_icon_hk.png new file mode 100644 index 0000000..2f5b015 Binary files /dev/null and b/ios/assets/images/wechat/c2c_hongbao_icon_hk.png differ diff --git a/ios/assets/images/wechat/c2c_received_icon@3x.png b/ios/assets/images/wechat/c2c_received_icon@3x.png new file mode 100644 index 0000000..cb315cd Binary files /dev/null and b/ios/assets/images/wechat/c2c_received_icon@3x.png differ diff --git a/ios/assets/images/wechat/c2c_rejected_icon@3x.png b/ios/assets/images/wechat/c2c_rejected_icon@3x.png new file mode 100644 index 0000000..66a2ffa Binary files /dev/null and b/ios/assets/images/wechat/c2c_rejected_icon@3x.png differ diff --git a/ios/assets/images/wechat/c2c_transfer_icon@3x.png b/ios/assets/images/wechat/c2c_transfer_icon@3x.png new file mode 100644 index 0000000..2e0f869 Binary files /dev/null and b/ios/assets/images/wechat/c2c_transfer_icon@3x.png differ diff --git a/ios/assets/images/wechat/callAnswerBtn@3x.png b/ios/assets/images/wechat/callAnswerBtn@3x.png new file mode 100644 index 0000000..7488217 Binary files /dev/null and b/ios/assets/images/wechat/callAnswerBtn@3x.png differ diff --git a/ios/assets/images/wechat/callAnswerBtnHL@3x.png b/ios/assets/images/wechat/callAnswerBtnHL@3x.png new file mode 100644 index 0000000..d48e70b Binary files /dev/null and b/ios/assets/images/wechat/callAnswerBtnHL@3x.png differ diff --git a/ios/assets/images/wechat/callAnswerBtniP4HL@2x.png b/ios/assets/images/wechat/callAnswerBtniP4HL@2x.png new file mode 100644 index 0000000..1e9a7eb Binary files /dev/null and b/ios/assets/images/wechat/callAnswerBtniP4HL@2x.png differ diff --git a/ios/assets/images/wechat/callDeclineBtn@3x.png b/ios/assets/images/wechat/callDeclineBtn@3x.png new file mode 100644 index 0000000..2fdd8c0 Binary files /dev/null and b/ios/assets/images/wechat/callDeclineBtn@3x.png differ diff --git a/ios/assets/images/wechat/callDeclineBtnHL@3x.png b/ios/assets/images/wechat/callDeclineBtnHL@3x.png new file mode 100644 index 0000000..03e3457 Binary files /dev/null and b/ios/assets/images/wechat/callDeclineBtnHL@3x.png differ diff --git a/ios/assets/images/wechat/callDeclineBtniP4HL@2x.png b/ios/assets/images/wechat/callDeclineBtniP4HL@2x.png new file mode 100644 index 0000000..79bec00 Binary files /dev/null and b/ios/assets/images/wechat/callDeclineBtniP4HL@2x.png differ diff --git a/ios/assets/images/wechat/card_delete_hl@2x.png b/ios/assets/images/wechat/card_delete_hl@2x.png new file mode 100644 index 0000000..337fb7a Binary files /dev/null and b/ios/assets/images/wechat/card_delete_hl@2x.png differ diff --git a/ios/assets/images/wechat/contactflag_star_mark@3x.png b/ios/assets/images/wechat/contactflag_star_mark@3x.png new file mode 100644 index 0000000..9656516 Binary files /dev/null and b/ios/assets/images/wechat/contactflag_star_mark@3x.png differ diff --git a/ios/assets/images/wechat/contactflag_star_mark_full@2x.png b/ios/assets/images/wechat/contactflag_star_mark_full@2x.png new file mode 100644 index 0000000..2f8447b Binary files /dev/null and b/ios/assets/images/wechat/contactflag_star_mark_full@2x.png differ diff --git a/ios/assets/images/wechat/contacts_add_friend@3x.png b/ios/assets/images/wechat/contacts_add_friend@3x.png new file mode 100644 index 0000000..5364be4 Binary files /dev/null and b/ios/assets/images/wechat/contacts_add_friend@3x.png differ diff --git a/ios/assets/images/wechat/contacts_add_myablum@2x.png b/ios/assets/images/wechat/contacts_add_myablum@2x.png new file mode 100644 index 0000000..03ee11e Binary files /dev/null and b/ios/assets/images/wechat/contacts_add_myablum@2x.png differ diff --git a/ios/assets/images/wechat/contacts_add_mycard@2x.png b/ios/assets/images/wechat/contacts_add_mycard@2x.png new file mode 100644 index 0000000..639d1f6 Binary files /dev/null and b/ios/assets/images/wechat/contacts_add_mycard@2x.png differ diff --git a/ios/assets/images/wechat/contacts_add_nearby@2x.png b/ios/assets/images/wechat/contacts_add_nearby@2x.png new file mode 100644 index 0000000..f905c85 Binary files /dev/null and b/ios/assets/images/wechat/contacts_add_nearby@2x.png differ diff --git a/ios/assets/images/wechat/contacts_add_newmessage@2x.png b/ios/assets/images/wechat/contacts_add_newmessage@2x.png new file mode 100644 index 0000000..cfa8c09 Binary files /dev/null and b/ios/assets/images/wechat/contacts_add_newmessage@2x.png differ diff --git a/ios/assets/images/wechat/contacts_add_newmessage@3x.png b/ios/assets/images/wechat/contacts_add_newmessage@3x.png new file mode 100644 index 0000000..c95ca02 Binary files /dev/null and b/ios/assets/images/wechat/contacts_add_newmessage@3x.png differ diff --git a/ios/assets/images/wechat/contacts_add_photo@2x.png b/ios/assets/images/wechat/contacts_add_photo@2x.png new file mode 100644 index 0000000..99c96c5 Binary files /dev/null and b/ios/assets/images/wechat/contacts_add_photo@2x.png differ diff --git a/ios/assets/images/wechat/contacts_add_radar@2x.png b/ios/assets/images/wechat/contacts_add_radar@2x.png new file mode 100644 index 0000000..3f849e1 Binary files /dev/null and b/ios/assets/images/wechat/contacts_add_radar@2x.png differ diff --git a/ios/assets/images/wechat/contacts_add_scan@2x.png b/ios/assets/images/wechat/contacts_add_scan@2x.png new file mode 100644 index 0000000..978a700 Binary files /dev/null and b/ios/assets/images/wechat/contacts_add_scan@2x.png differ diff --git a/ios/assets/images/wechat/contacts_add_scan@3x.png b/ios/assets/images/wechat/contacts_add_scan@3x.png new file mode 100644 index 0000000..960eec2 Binary files /dev/null and b/ios/assets/images/wechat/contacts_add_scan@3x.png differ diff --git a/ios/assets/images/wechat/contacts_add_shake@2x.png b/ios/assets/images/wechat/contacts_add_shake@2x.png new file mode 100644 index 0000000..c74cc03 Binary files /dev/null and b/ios/assets/images/wechat/contacts_add_shake@2x.png differ diff --git a/ios/assets/images/wechat/contacts_add_sticker@2x.png b/ios/assets/images/wechat/contacts_add_sticker@2x.png new file mode 100644 index 0000000..81979c0 Binary files /dev/null and b/ios/assets/images/wechat/contacts_add_sticker@2x.png differ diff --git a/ios/assets/images/wechat/contacts_add_voip@2x.png b/ios/assets/images/wechat/contacts_add_voip@2x.png new file mode 100644 index 0000000..301444c Binary files /dev/null and b/ios/assets/images/wechat/contacts_add_voip@2x.png differ diff --git a/ios/assets/images/wechat/contacts_add_webwechat@2x.png b/ios/assets/images/wechat/contacts_add_webwechat@2x.png new file mode 100644 index 0000000..f6eaae5 Binary files /dev/null and b/ios/assets/images/wechat/contacts_add_webwechat@2x.png differ diff --git a/ios/assets/images/wechat/contacts_audiocall@2x.png b/ios/assets/images/wechat/contacts_audiocall@2x.png new file mode 100644 index 0000000..6185835 Binary files /dev/null and b/ios/assets/images/wechat/contacts_audiocall@2x.png differ diff --git a/ios/assets/images/wechat/contacts_home_icon@2x.png b/ios/assets/images/wechat/contacts_home_icon@2x.png new file mode 100644 index 0000000..6800535 Binary files /dev/null and b/ios/assets/images/wechat/contacts_home_icon@2x.png differ diff --git a/ios/assets/images/wechat/contacts_videocall@2x.png b/ios/assets/images/wechat/contacts_videocall@2x.png new file mode 100644 index 0000000..42c7031 Binary files /dev/null and b/ios/assets/images/wechat/contacts_videocall@2x.png differ diff --git a/ios/assets/images/wechat/emoji_download_icon.png b/ios/assets/images/wechat/emoji_download_icon.png new file mode 100644 index 0000000..51b6213 Binary files /dev/null and b/ios/assets/images/wechat/emoji_download_icon.png differ diff --git a/ios/assets/images/wechat/emoji_download_icon_samll.png b/ios/assets/images/wechat/emoji_download_icon_samll.png new file mode 100644 index 0000000..c549580 Binary files /dev/null and b/ios/assets/images/wechat/emoji_download_icon_samll.png differ diff --git a/ios/assets/images/wechat/emoji_unselected.png b/ios/assets/images/wechat/emoji_unselected.png new file mode 100644 index 0000000..8b8c6d5 Binary files /dev/null and b/ios/assets/images/wechat/emoji_unselected.png differ diff --git a/ios/assets/images/wechat/ff_IconBottle@3x.png b/ios/assets/images/wechat/ff_IconBottle@3x.png new file mode 100644 index 0000000..3b9914d Binary files /dev/null and b/ios/assets/images/wechat/ff_IconBottle@3x.png differ diff --git a/ios/assets/images/wechat/ff_IconBrowse1@3x.png b/ios/assets/images/wechat/ff_IconBrowse1@3x.png new file mode 100644 index 0000000..5b675a6 Binary files /dev/null and b/ios/assets/images/wechat/ff_IconBrowse1@3x.png differ diff --git a/ios/assets/images/wechat/ff_IconGroup@2x.png b/ios/assets/images/wechat/ff_IconGroup@2x.png new file mode 100644 index 0000000..1002c38 Binary files /dev/null and b/ios/assets/images/wechat/ff_IconGroup@2x.png differ diff --git a/ios/assets/images/wechat/ff_IconLocationService@3x.png b/ios/assets/images/wechat/ff_IconLocationService@3x.png new file mode 100644 index 0000000..884ea08 Binary files /dev/null and b/ios/assets/images/wechat/ff_IconLocationService@3x.png differ diff --git a/ios/assets/images/wechat/ff_IconNearby@3x.png b/ios/assets/images/wechat/ff_IconNearby@3x.png new file mode 100644 index 0000000..7557465 Binary files /dev/null and b/ios/assets/images/wechat/ff_IconNearby@3x.png differ diff --git a/ios/assets/images/wechat/ff_IconQRCode@3x.png b/ios/assets/images/wechat/ff_IconQRCode@3x.png new file mode 100644 index 0000000..a504cdd Binary files /dev/null and b/ios/assets/images/wechat/ff_IconQRCode@3x.png differ diff --git a/ios/assets/images/wechat/ff_IconSearch1@3x.png b/ios/assets/images/wechat/ff_IconSearch1@3x.png new file mode 100644 index 0000000..823cb43 Binary files /dev/null and b/ios/assets/images/wechat/ff_IconSearch1@3x.png differ diff --git a/ios/assets/images/wechat/ff_IconShake@3x.png b/ios/assets/images/wechat/ff_IconShake@3x.png new file mode 100644 index 0000000..86031dc Binary files /dev/null and b/ios/assets/images/wechat/ff_IconShake@3x.png differ diff --git a/ios/assets/images/wechat/ff_IconShowAlbum@3x.png b/ios/assets/images/wechat/ff_IconShowAlbum@3x.png new file mode 100644 index 0000000..c95da29 Binary files /dev/null and b/ios/assets/images/wechat/ff_IconShowAlbum@3x.png differ diff --git a/ios/assets/images/wechat/ff_IconShowMobile@2x.png b/ios/assets/images/wechat/ff_IconShowMobile@2x.png new file mode 100644 index 0000000..d470faf Binary files /dev/null and b/ios/assets/images/wechat/ff_IconShowMobile@2x.png differ diff --git a/ios/assets/images/wechat/ff_IconWCO@3x.png b/ios/assets/images/wechat/ff_IconWCO@3x.png new file mode 100644 index 0000000..4962dce Binary files /dev/null and b/ios/assets/images/wechat/ff_IconWCO@3x.png differ diff --git a/ios/assets/images/wechat/ff_search_history_delete@3x.png b/ios/assets/images/wechat/ff_search_history_delete@3x.png new file mode 100644 index 0000000..2160157 Binary files /dev/null and b/ios/assets/images/wechat/ff_search_history_delete@3x.png differ diff --git a/ios/assets/images/wechat/ff_search_magnifier@3x.png b/ios/assets/images/wechat/ff_search_magnifier@3x.png new file mode 100644 index 0000000..cb0e663 Binary files /dev/null and b/ios/assets/images/wechat/ff_search_magnifier@3x.png differ diff --git a/ios/assets/images/wechat/ff_search_sug_fill@3x.png b/ios/assets/images/wechat/ff_search_sug_fill@3x.png new file mode 100644 index 0000000..036fc16 Binary files /dev/null and b/ios/assets/images/wechat/ff_search_sug_fill@3x.png differ diff --git a/ios/assets/images/wechat/fileicon_folder48@2x.png b/ios/assets/images/wechat/fileicon_folder48@2x.png new file mode 100644 index 0000000..a5c8cc7 Binary files /dev/null and b/ios/assets/images/wechat/fileicon_folder48@2x.png differ diff --git a/ios/assets/images/wechat/fileicon_link120@3x.png b/ios/assets/images/wechat/fileicon_link120@3x.png new file mode 100644 index 0000000..5102615 Binary files /dev/null and b/ios/assets/images/wechat/fileicon_link120@3x.png differ diff --git a/ios/assets/images/wechat/fileicon_location120@3x.png b/ios/assets/images/wechat/fileicon_location120@3x.png new file mode 100644 index 0000000..bda110f Binary files /dev/null and b/ios/assets/images/wechat/fileicon_location120@3x.png differ diff --git a/ios/assets/images/wechat/fileicon_music120@3x.png b/ios/assets/images/wechat/fileicon_music120@3x.png new file mode 100644 index 0000000..e961ce4 Binary files /dev/null and b/ios/assets/images/wechat/fileicon_music120@3x.png differ diff --git a/ios/assets/images/wechat/fileicon_numbers120@3x.png b/ios/assets/images/wechat/fileicon_numbers120@3x.png new file mode 100644 index 0000000..de626ba Binary files /dev/null and b/ios/assets/images/wechat/fileicon_numbers120@3x.png differ diff --git a/ios/assets/images/wechat/fileicon_pages120@3x.png b/ios/assets/images/wechat/fileicon_pages120@3x.png new file mode 100644 index 0000000..08b8914 Binary files /dev/null and b/ios/assets/images/wechat/fileicon_pages120@3x.png differ diff --git a/ios/assets/images/wechat/fileicon_pdf120@3x.png b/ios/assets/images/wechat/fileicon_pdf120@3x.png new file mode 100644 index 0000000..5674f53 Binary files /dev/null and b/ios/assets/images/wechat/fileicon_pdf120@3x.png differ diff --git a/ios/assets/images/wechat/fileicon_pic120@3x.png b/ios/assets/images/wechat/fileicon_pic120@3x.png new file mode 100644 index 0000000..2cd6f0a Binary files /dev/null and b/ios/assets/images/wechat/fileicon_pic120@3x.png differ diff --git a/ios/assets/images/wechat/fileicon_ppt120@3x.png b/ios/assets/images/wechat/fileicon_ppt120@3x.png new file mode 100644 index 0000000..c129ff1 Binary files /dev/null and b/ios/assets/images/wechat/fileicon_ppt120@3x.png differ diff --git a/ios/assets/images/wechat/fileicon_sound120@3x.png b/ios/assets/images/wechat/fileicon_sound120@3x.png new file mode 100644 index 0000000..9c0b5f0 Binary files /dev/null and b/ios/assets/images/wechat/fileicon_sound120@3x.png differ diff --git a/ios/assets/images/wechat/fileicon_txt120@3x.png b/ios/assets/images/wechat/fileicon_txt120@3x.png new file mode 100644 index 0000000..6208b03 Binary files /dev/null and b/ios/assets/images/wechat/fileicon_txt120@3x.png differ diff --git a/ios/assets/images/wechat/fileicon_txt48@2x.png b/ios/assets/images/wechat/fileicon_txt48@2x.png new file mode 100644 index 0000000..31b23c8 Binary files /dev/null and b/ios/assets/images/wechat/fileicon_txt48@2x.png differ diff --git a/ios/assets/images/wechat/fileicon_unkown120@2x.png b/ios/assets/images/wechat/fileicon_unkown120@2x.png new file mode 100644 index 0000000..ac2cf3e Binary files /dev/null and b/ios/assets/images/wechat/fileicon_unkown120@2x.png differ diff --git a/ios/assets/images/wechat/fileicon_video120@3x.png b/ios/assets/images/wechat/fileicon_video120@3x.png new file mode 100644 index 0000000..7cd7696 Binary files /dev/null and b/ios/assets/images/wechat/fileicon_video120@3x.png differ diff --git a/ios/assets/images/wechat/fileicon_voice120@3x.png b/ios/assets/images/wechat/fileicon_voice120@3x.png new file mode 100644 index 0000000..76af94d Binary files /dev/null and b/ios/assets/images/wechat/fileicon_voice120@3x.png differ diff --git a/ios/assets/images/wechat/fileicon_word120@3x.png b/ios/assets/images/wechat/fileicon_word120@3x.png new file mode 100644 index 0000000..9599953 Binary files /dev/null and b/ios/assets/images/wechat/fileicon_word120@3x.png differ diff --git a/ios/assets/images/wechat/fileicon_word48@2x.png b/ios/assets/images/wechat/fileicon_word48@2x.png new file mode 100644 index 0000000..17be8f6 Binary files /dev/null and b/ios/assets/images/wechat/fileicon_word48@2x.png differ diff --git a/ios/assets/images/wechat/fileicon_xls120@3x.png b/ios/assets/images/wechat/fileicon_xls120@3x.png new file mode 100644 index 0000000..73ff8c3 Binary files /dev/null and b/ios/assets/images/wechat/fileicon_xls120@3x.png differ diff --git a/ios/assets/images/wechat/fileicon_zip120@3x.png b/ios/assets/images/wechat/fileicon_zip120@3x.png new file mode 100644 index 0000000..8adea3c Binary files /dev/null and b/ios/assets/images/wechat/fileicon_zip120@3x.png differ diff --git a/ios/assets/images/wechat/flip_camera_icon_nor@3x.png b/ios/assets/images/wechat/flip_camera_icon_nor@3x.png new file mode 100644 index 0000000..c28559c Binary files /dev/null and b/ios/assets/images/wechat/flip_camera_icon_nor@3x.png differ diff --git a/ios/assets/images/wechat/flip_camera_icon_pre@3x.png b/ios/assets/images/wechat/flip_camera_icon_pre@3x.png new file mode 100644 index 0000000..f756d61 Binary files /dev/null and b/ios/assets/images/wechat/flip_camera_icon_pre@3x.png differ diff --git a/ios/assets/images/wechat/fts_new_group@3x.png b/ios/assets/images/wechat/fts_new_group@3x.png new file mode 100644 index 0000000..449630f Binary files /dev/null and b/ios/assets/images/wechat/fts_new_group@3x.png differ diff --git a/ios/assets/images/wechat/fts_search_wechat_icon@2x.png b/ios/assets/images/wechat/fts_search_wechat_icon@2x.png new file mode 100644 index 0000000..f5dec34 Binary files /dev/null and b/ios/assets/images/wechat/fts_search_wechat_icon@2x.png differ diff --git a/ios/assets/images/wechat/fts_searchicon_brandcontact@3x.png b/ios/assets/images/wechat/fts_searchicon_brandcontact@3x.png new file mode 100644 index 0000000..9adbaf7 Binary files /dev/null and b/ios/assets/images/wechat/fts_searchicon_brandcontact@3x.png differ diff --git a/ios/assets/images/wechat/fts_searchicon_emoji@3x.png b/ios/assets/images/wechat/fts_searchicon_emoji@3x.png new file mode 100644 index 0000000..1c117e0 Binary files /dev/null and b/ios/assets/images/wechat/fts_searchicon_emoji@3x.png differ diff --git a/ios/assets/images/wechat/fts_searchicon_magnifier@3x.png b/ios/assets/images/wechat/fts_searchicon_magnifier@3x.png new file mode 100644 index 0000000..ece8483 Binary files /dev/null and b/ios/assets/images/wechat/fts_searchicon_magnifier@3x.png differ diff --git a/ios/assets/images/wechat/fts_searchicon_music@3x.png b/ios/assets/images/wechat/fts_searchicon_music@3x.png new file mode 100644 index 0000000..8fca288 Binary files /dev/null and b/ios/assets/images/wechat/fts_searchicon_music@3x.png differ diff --git a/ios/assets/images/wechat/fts_searchicon_novel@3x.png b/ios/assets/images/wechat/fts_searchicon_novel@3x.png new file mode 100644 index 0000000..2a3be77 Binary files /dev/null and b/ios/assets/images/wechat/fts_searchicon_novel@3x.png differ diff --git a/ios/assets/images/wechat/game_topic_create@3x.png b/ios/assets/images/wechat/game_topic_create@3x.png new file mode 100644 index 0000000..67cd9b7 Binary files /dev/null and b/ios/assets/images/wechat/game_topic_create@3x.png differ diff --git a/ios/assets/images/wechat/groupPay_BigIcon@3x.png b/ios/assets/images/wechat/groupPay_BigIcon@3x.png new file mode 100644 index 0000000..367ec46 Binary files /dev/null and b/ios/assets/images/wechat/groupPay_BigIcon@3x.png differ diff --git a/ios/assets/images/wechat/kinda_wechat_pay.png b/ios/assets/images/wechat/kinda_wechat_pay.png new file mode 100644 index 0000000..496bc6f Binary files /dev/null and b/ios/assets/images/wechat/kinda_wechat_pay.png differ diff --git a/ios/assets/images/wechat/kinda_wechat_pay@3x.png b/ios/assets/images/wechat/kinda_wechat_pay@3x.png new file mode 100644 index 0000000..2f5fde9 Binary files /dev/null and b/ios/assets/images/wechat/kinda_wechat_pay@3x.png differ diff --git a/ios/assets/images/wechat/kinda_wechat_pay_light.png b/ios/assets/images/wechat/kinda_wechat_pay_light.png new file mode 100644 index 0000000..3b88aa9 Binary files /dev/null and b/ios/assets/images/wechat/kinda_wechat_pay_light.png differ diff --git a/ios/assets/images/wechat/kinda_wechatpay_loading_icon.png b/ios/assets/images/wechat/kinda_wechatpay_loading_icon.png new file mode 100644 index 0000000..001cd85 Binary files /dev/null and b/ios/assets/images/wechat/kinda_wechatpay_loading_icon.png differ diff --git a/ios/assets/images/wechat/kinda_wechatpay_notify.png b/ios/assets/images/wechat/kinda_wechatpay_notify.png new file mode 100644 index 0000000..7774c30 Binary files /dev/null and b/ios/assets/images/wechat/kinda_wechatpay_notify.png differ diff --git a/ios/assets/images/wechat/kinda_wechatpay_notify@3x.png b/ios/assets/images/wechat/kinda_wechatpay_notify@3x.png new file mode 100644 index 0000000..3364d9a Binary files /dev/null and b/ios/assets/images/wechat/kinda_wechatpay_notify@3x.png differ diff --git a/ios/assets/images/wechat/kinda_wxp_charge_success.png b/ios/assets/images/wechat/kinda_wxp_charge_success.png new file mode 100644 index 0000000..fa3e9f0 Binary files /dev/null and b/ios/assets/images/wechat/kinda_wxp_charge_success.png differ diff --git a/ios/assets/images/wechat/kinda_wxp_transfer_cancel.png b/ios/assets/images/wechat/kinda_wxp_transfer_cancel.png new file mode 100644 index 0000000..a38e25b Binary files /dev/null and b/ios/assets/images/wechat/kinda_wxp_transfer_cancel.png differ diff --git a/ios/assets/images/wechat/kinda_wxp_transfer_cancel@3x.png b/ios/assets/images/wechat/kinda_wxp_transfer_cancel@3x.png new file mode 100644 index 0000000..7fccb85 Binary files /dev/null and b/ios/assets/images/wechat/kinda_wxp_transfer_cancel@3x.png differ diff --git a/ios/assets/images/wechat/kinda_wxp_transfer_status_delay_wait.png b/ios/assets/images/wechat/kinda_wxp_transfer_status_delay_wait.png new file mode 100644 index 0000000..7dc83a9 Binary files /dev/null and b/ios/assets/images/wechat/kinda_wxp_transfer_status_delay_wait.png differ diff --git a/ios/assets/images/wechat/kinda_wxp_transfer_status_delay_wait@3x.png b/ios/assets/images/wechat/kinda_wxp_transfer_status_delay_wait@3x.png new file mode 100644 index 0000000..6006b17 Binary files /dev/null and b/ios/assets/images/wechat/kinda_wxp_transfer_status_delay_wait@3x.png differ diff --git a/ios/assets/images/wechat/kinda_wxp_transfer_status_receiving.png b/ios/assets/images/wechat/kinda_wxp_transfer_status_receiving.png new file mode 100644 index 0000000..5366af7 Binary files /dev/null and b/ios/assets/images/wechat/kinda_wxp_transfer_status_receiving.png differ diff --git a/ios/assets/images/wechat/kinda_wxp_transfer_status_refund.png b/ios/assets/images/wechat/kinda_wxp_transfer_status_refund.png new file mode 100644 index 0000000..dc626f2 Binary files /dev/null and b/ios/assets/images/wechat/kinda_wxp_transfer_status_refund.png differ diff --git a/ios/assets/images/wechat/kinda_wxp_transfer_status_timeout.png b/ios/assets/images/wechat/kinda_wxp_transfer_status_timeout.png new file mode 100644 index 0000000..6e37bc3 Binary files /dev/null and b/ios/assets/images/wechat/kinda_wxp_transfer_status_timeout.png differ diff --git a/ios/assets/images/wechat/language_selected@3x.png b/ios/assets/images/wechat/language_selected@3x.png new file mode 100644 index 0000000..cc8e957 Binary files /dev/null and b/ios/assets/images/wechat/language_selected@3x.png differ diff --git a/ios/assets/images/wechat/licaitong@3x.png b/ios/assets/images/wechat/licaitong@3x.png new file mode 100644 index 0000000..5fa5422 Binary files /dev/null and b/ios/assets/images/wechat/licaitong@3x.png differ diff --git a/ios/assets/images/wechat/licaitong_ico@3x.png b/ios/assets/images/wechat/licaitong_ico@3x.png new file mode 100644 index 0000000..666d69e Binary files /dev/null and b/ios/assets/images/wechat/licaitong_ico@3x.png differ diff --git a/ios/assets/images/wechat/local_search_icon@3x.png b/ios/assets/images/wechat/local_search_icon@3x.png new file mode 100644 index 0000000..ece8483 Binary files /dev/null and b/ios/assets/images/wechat/local_search_icon@3x.png differ diff --git a/ios/assets/images/wechat/locationSharing_icon_Member@2x.png b/ios/assets/images/wechat/locationSharing_icon_Member@2x.png new file mode 100644 index 0000000..7c4f91d Binary files /dev/null and b/ios/assets/images/wechat/locationSharing_icon_Member@2x.png differ diff --git a/ios/assets/images/wechat/locationSharing_icon_click_Member@2x.png b/ios/assets/images/wechat/locationSharing_icon_click_Member@2x.png new file mode 100644 index 0000000..7bd7038 Binary files /dev/null and b/ios/assets/images/wechat/locationSharing_icon_click_Member@2x.png differ diff --git a/ios/assets/images/wechat/locationSharing_mylocation_HL@2x.png b/ios/assets/images/wechat/locationSharing_mylocation_HL@2x.png new file mode 100644 index 0000000..066fcf9 Binary files /dev/null and b/ios/assets/images/wechat/locationSharing_mylocation_HL@2x.png differ diff --git a/ios/assets/images/wechat/locationSharing_navigate_icon_HL_new@3x.png b/ios/assets/images/wechat/locationSharing_navigate_icon_HL_new@3x.png new file mode 100644 index 0000000..c6b571b Binary files /dev/null and b/ios/assets/images/wechat/locationSharing_navigate_icon_HL_new@3x.png differ diff --git a/ios/assets/images/wechat/locationSharing_navigate_icon_new@3x.png b/ios/assets/images/wechat/locationSharing_navigate_icon_new@3x.png new file mode 100644 index 0000000..d5c3622 Binary files /dev/null and b/ios/assets/images/wechat/locationSharing_navigate_icon_new@3x.png differ diff --git a/ios/assets/images/wechat/location_my@3x.png b/ios/assets/images/wechat/location_my@3x.png new file mode 100644 index 0000000..55250b0 Binary files /dev/null and b/ios/assets/images/wechat/location_my@3x.png differ diff --git a/ios/assets/images/wechat/location_my_current@2x.png b/ios/assets/images/wechat/location_my_current@2x.png new file mode 100644 index 0000000..4fec1e4 Binary files /dev/null and b/ios/assets/images/wechat/location_my_current@2x.png differ diff --git a/ios/assets/images/wechat/log_logo@3x.png b/ios/assets/images/wechat/log_logo@3x.png new file mode 100644 index 0000000..ed43c8f Binary files /dev/null and b/ios/assets/images/wechat/log_logo@3x.png differ diff --git a/ios/assets/images/wechat/machelper-button-locked@3x.png b/ios/assets/images/wechat/machelper-button-locked@3x.png new file mode 100644 index 0000000..fb8e185 Binary files /dev/null and b/ios/assets/images/wechat/machelper-button-locked@3x.png differ diff --git a/ios/assets/images/wechat/mailToolBarIcon2@3x.png b/ios/assets/images/wechat/mailToolBarIcon2@3x.png new file mode 100644 index 0000000..42e21a6 Binary files /dev/null and b/ios/assets/images/wechat/mailToolBarIcon2@3x.png differ diff --git a/ios/assets/images/wechat/mailToolBarIcon@3x.png b/ios/assets/images/wechat/mailToolBarIcon@3x.png new file mode 100644 index 0000000..c50b3d8 Binary files /dev/null and b/ios/assets/images/wechat/mailToolBarIcon@3x.png differ diff --git a/ios/assets/images/wechat/mail_add_contact_pressed@2x.png b/ios/assets/images/wechat/mail_add_contact_pressed@2x.png new file mode 100644 index 0000000..a8114d9 Binary files /dev/null and b/ios/assets/images/wechat/mail_add_contact_pressed@2x.png differ diff --git a/ios/assets/images/wechat/mailapp_addAttachicon_HL@2x.png b/ios/assets/images/wechat/mailapp_addAttachicon_HL@2x.png new file mode 100644 index 0000000..f12a497 Binary files /dev/null and b/ios/assets/images/wechat/mailapp_addAttachicon_HL@2x.png differ diff --git a/ios/assets/images/wechat/multitalkNetworkMark@3x.png b/ios/assets/images/wechat/multitalkNetworkMark@3x.png new file mode 100644 index 0000000..c585c5d Binary files /dev/null and b/ios/assets/images/wechat/multitalkNetworkMark@3x.png differ diff --git a/ios/assets/images/wechat/pencilBubble@3x.png b/ios/assets/images/wechat/pencilBubble@3x.png new file mode 100644 index 0000000..6fe9368 Binary files /dev/null and b/ios/assets/images/wechat/pencilBubble@3x.png differ diff --git a/ios/assets/images/wechat/return_icon_nor@2x.png b/ios/assets/images/wechat/return_icon_nor@2x.png new file mode 100644 index 0000000..dd9e922 Binary files /dev/null and b/ios/assets/images/wechat/return_icon_nor@2x.png differ diff --git a/ios/assets/images/wechat/rewardCode_checkBox_Select@3x.png b/ios/assets/images/wechat/rewardCode_checkBox_Select@3x.png new file mode 100644 index 0000000..85b54f6 Binary files /dev/null and b/ios/assets/images/wechat/rewardCode_checkBox_Select@3x.png differ diff --git a/ios/assets/images/wechat/save_icon_nor@2x.png b/ios/assets/images/wechat/save_icon_nor@2x.png new file mode 100644 index 0000000..7b8d9be Binary files /dev/null and b/ios/assets/images/wechat/save_icon_nor@2x.png differ diff --git a/ios/assets/images/wechat/setting_locationServices@2x.png b/ios/assets/images/wechat/setting_locationServices@2x.png new file mode 100644 index 0000000..ddf73c3 Binary files /dev/null and b/ios/assets/images/wechat/setting_locationServices@2x.png differ diff --git a/ios/assets/images/wechat/setting_locationServicesDisable@2x.png b/ios/assets/images/wechat/setting_locationServicesDisable@2x.png new file mode 100644 index 0000000..b62d9f8 Binary files /dev/null and b/ios/assets/images/wechat/setting_locationServicesDisable@2x.png differ diff --git a/ios/assets/video.json b/ios/assets/video.json new file mode 100644 index 0000000..bd1d245 --- /dev/null +++ b/ios/assets/video.json @@ -0,0 +1,126 @@ +{ + "categories": [ + { + "name": "Movies", + "videos": [ + { + "description": "Big Buck Bunny tells the story of a giant rabbit with a heart bigger than himself. When one sunny day three rodents rudely harass him, something snaps... and the rabbit ain't no bunny anymore! In the typical cartoon tradition he prepares the nasty rodents a comical revenge.\n\nLicensed under the Creative Commons Attribution license\nhttp://www.bigbuckbunny.org", + "sources": [ + "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" + ], + "subtitle": "By Blender Foundation", + "thumb": "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/images/BigBuckBunny.jpg", + "title": "Big Buck Bunny" + }, + { + "description": "The first Blender Open Movie from 2006", + "sources": [ + "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4" + ], + "subtitle": "By Blender Foundation", + "thumb": "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/images/ElephantsDream.jpg", + "title": "Elephant Dream" + }, + { + "description": "HBO GO now works with Chromecast -- the easiest way to enjoy online video on your TV. For when you want to settle into your Iron Throne to watch the latest episodes. For $35.\nLearn how to use Chromecast with HBO GO and more at google.com/chromecast.", + "sources": [ + "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerBlazes.mp4" + ], + "subtitle": "By Google", + "thumb": "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/images/ForBiggerBlazes.jpg", + "title": "For Bigger Blazes" + }, + { + "description": "Introducing Chromecast. The easiest way to enjoy online video and music on your TV—for when Batman's escapes aren't quite big enough. For $35. Learn how to use Chromecast with Google Play Movies and more at google.com/chromecast.", + "sources": [ + "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerEscapes.mp4" + ], + "subtitle": "By Google", + "thumb": "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/images/ForBiggerEscapes.jpg", + "title": "For Bigger Escape" + }, + { + "description": "Introducing Chromecast. The easiest way to enjoy online video and music on your TV. For $35. Find out more at google.com/chromecast.", + "sources": [ + "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerFun.mp4" + ], + "subtitle": "By Google", + "thumb": "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/images/ForBiggerFun.jpg", + "title": "For Bigger Fun" + }, + { + "description": "Introducing Chromecast. The easiest way to enjoy online video and music on your TV—for the times that call for bigger joyrides. For $35. Learn how to use Chromecast with YouTube and more at google.com/chromecast.", + "sources": [ + "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerJoyrides.mp4" + ], + "subtitle": "By Google", + "thumb": "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/images/ForBiggerJoyrides.jpg", + "title": "For Bigger Joyrides" + }, + { + "description": "Introducing Chromecast. The easiest way to enjoy online video and music on your TV—for when you want to make Buster's big meltdowns even bigger. For $35. Learn how to use Chromecast with Netflix and more at google.com/chromecast.", + "sources": [ + "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerMeltdowns.mp4" + ], + "subtitle": "By Google", + "thumb": "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/images/ForBiggerMeltdowns.jpg", + "title": "For Bigger Meltdowns" + }, + { + "description": "Sintel is an independently produced short film, initiated by the Blender Foundation as a means to further improve and validate the free/open source 3D creation suite Blender. With initial funding provided by 1000s of donations via the internet community, it has again proven to be a viable development model for both open 3D technology as for independent animation film.\nThis 15 minute film has been realized in the studio of the Amsterdam Blender Institute, by an international team of artists and developers. In addition to that, several crucial technical and creative targets have been realized online, by developers and artists and teams all over the world.\nwww.sintel.org", + "sources": [ + "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/Sintel.mp4" + ], + "subtitle": "By Blender Foundation", + "thumb": "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/images/Sintel.jpg", + "title": "Sintel" + }, + { + "description": "Smoking Tire takes the all-new Subaru Outback to the highest point we can find in hopes our customer-appreciation Balloon Launch will get some free T-shirts into the hands of our viewers.", + "sources": [ + "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/SubaruOutbackOnStreetAndDirt.mp4" + ], + "subtitle": "By Garage419", + "thumb": "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/images/SubaruOutbackOnStreetAndDirt.jpg", + "title": "Subaru Outback On Street And Dirt" + }, + { + "description": "Tears of Steel was realized with crowd-funding by users of the open source 3D creation tool Blender. Target was to improve and test a complete open and free pipeline for visual effects in film - and to make a compelling sci-fi film in Amsterdam, the Netherlands. The film itself, and all raw material used for making it, have been released under the Creatieve Commons 3.0 Attribution license. Visit the tearsofsteel.org website to find out more about this, or to purchase the 4-DVD box with a lot of extras. (CC) Blender Foundation - http://www.tearsofsteel.org", + "sources": [ + "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/TearsOfSteel.mp4" + ], + "subtitle": "By Blender Foundation", + "thumb": "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/images/TearsOfSteel.jpg", + "title": "Tears of Steel" + }, + { + "description": "The Smoking Tire heads out to Adams Motorsports Park in Riverside, CA to test the most requested car of 2010, the Volkswagen GTI. Will it beat the Mazdaspeed3's standard-setting lap time? Watch and see...", + "sources": [ + "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/VolkswagenGTIReview.mp4" + ], + "subtitle": "By Garage419", + "thumb": "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/images/VolkswagenGTIReview.jpg", + "title": "Volkswagen GTI Review" + }, + { + "description": "The Smoking Tire is going on the 2010 Bullrun Live Rally in a 2011 Shelby GT500, and posting a video from the road every single day! The only place to watch them is by subscribing to The Smoking Tire or watching at BlackMagicShine.com", + "sources": [ + "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/WeAreGoingOnBullrun.mp4" + ], + "subtitle": "By Garage419", + "thumb": "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/images/WeAreGoingOnBullrun.jpg", + "title": "We Are Going On Bullrun" + }, + { + "description": "The Smoking Tire meets up with Chris and Jorge from CarsForAGrand.com to see just how far $1,000 can go when looking for a car.The Smoking Tire meets up with Chris and Jorge from CarsForAGrand.com to see just how far $1,000 can go when looking for a car.", + "sources": [ + "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/WhatCarCanYouGetForAGrand.mp4" + ], + "subtitle": "By Garage419", + "thumb": "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/images/WhatCarCanYouGetForAGrand.jpg", + "title": "What care can you get for a grand?" + } + ] + } + ] + } \ No newline at end of file diff --git a/lib/app/constants/size_config.dart b/lib/app/constants/size_config.dart index 2e2738c..4abd7ed 100644 --- a/lib/app/constants/size_config.dart +++ b/lib/app/constants/size_config.dart @@ -14,26 +14,101 @@ class SizeConfig { static double? screenHeight; static double? blockSizeHorizontal; static double? blockSizeVertical; + static bool _isInitialized = false; void init(BuildContext context) { + if (_isInitialized) return; + _mediaQueryData = MediaQuery.of(context); screenWidth = _mediaQueryData?.size.width; screenHeight = _mediaQueryData?.size.height; blockSizeHorizontal = (screenWidth ?? 0) / 100; blockSizeVertical = (screenHeight ?? 0) / 100; + _isInitialized = true; } static double getProportionateScreenHeight(double inputHeight) { + if (!_isInitialized || screenHeight == null || screenHeight == 0) { + return inputHeight; + } double safeHeight = screenHeight ?? 812.0; // fallback for typical iPhone height return (inputHeight / 812.0) * safeHeight; } static double getProportionateScreenWidth(double inputWidth) { + if (!_isInitialized || screenWidth == null || screenWidth == 0) { + return inputWidth; + } double safeWidth = screenWidth ?? 375.0; // fallback for typical iPhone width return (inputWidth / 375.0) * safeWidth; } -} + // Helper methods for common sizing + static double height(double value) => getProportionateScreenHeight(value); + static double width(double value) => getProportionateScreenWidth(value); + + // Font size utility + static double fontSize(double size) { + if (!_isInitialized || screenWidth == null || screenWidth == 0) return size; + return (size / 375.0) * (screenWidth ?? 375.0); + } + + // Responsive sizing based on screen size + static bool get isSmallScreen => (screenWidth ?? 0) < 360; + static bool get isMediumScreen => (screenWidth ?? 0) >= 360 && (screenWidth ?? 0) < 400; + static bool get isLargeScreen => (screenWidth ?? 0) >= 400; + + static double getResponsiveValue({ + required double small, + required double medium, + required double large, + }) { + if (isSmallScreen) return getProportionateScreenWidth(small); + if (isMediumScreen) return getProportionateScreenWidth(medium); + return getProportionateScreenWidth(large); + } + + // Padding and margin utilities + static EdgeInsets padding({ + double all = 0, + double? horizontal, + double? vertical, + double? left, + double? top, + double? right, + double? bottom, + }) { + if (all != 0) { + return EdgeInsets.all(getProportionateScreenWidth(all)); + } + return EdgeInsets.only( + left: getProportionateScreenWidth(left ?? 0), + top: getProportionateScreenHeight(top ?? 0), + right: getProportionateScreenWidth(right ?? 0), + bottom: getProportionateScreenHeight(bottom ?? 0), + ); + } + + static EdgeInsets margin({ + double all = 0, + double? horizontal, + double? vertical, + double? left, + double? top, + double? right, + double? bottom, + }) { + if (all != 0) { + return EdgeInsets.all(getProportionateScreenWidth(all)); + } + return EdgeInsets.only( + left: getProportionateScreenWidth(left ?? 0), + top: getProportionateScreenHeight(top ?? 0), + right: getProportionateScreenWidth(right ?? 0), + bottom: getProportionateScreenHeight(bottom ?? 0), + ); + } +} class VerticalSpacing extends StatelessWidget { final double height; diff --git a/lib/app/constants/size_usage_example.dart b/lib/app/constants/size_usage_example.dart new file mode 100644 index 0000000..0e27ab4 --- /dev/null +++ b/lib/app/constants/size_usage_example.dart @@ -0,0 +1,132 @@ +import 'package:flutter/material.dart'; +import 'size_config.dart'; + +/// Example usage of the updated SizeConfig utilities +/// This file demonstrates how to use responsive sizing in your Flutter app + +class SizeUsageExample extends StatelessWidget { + const SizeUsageExample({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + // Initialize SizeConfig in your main widget or app + SizeConfig().init(context); + + return Scaffold( + appBar: AppBar( + title: Text( + 'Size Utils Example', + style: TextStyle(fontSize: SizeConfig.fontSize(18)), + ), + ), + body: Padding( + padding: SizeConfig.padding(all: 16), + child: Column( + children: [ + // Using responsive height and width + Container( + width: SizeConfig.width(200), + height: SizeConfig.height(100), + color: Colors.blue, + child: Center( + child: Text( + 'Responsive Container', + style: TextStyle( + fontSize: SizeConfig.fontSize(16), + color: Colors.white, + ), + ), + ), + ), + + // Using VerticalSpacing widget + VerticalSpacing(20), + + // Using HorizontalSpacing widget + Row( + children: [ + Container( + width: SizeConfig.width(80), + height: SizeConfig.height(80), + color: Colors.green, + ), + HorizontalSpacing(10), + Container( + width: SizeConfig.width(80), + height: SizeConfig.height(80), + color: Colors.red, + ), + ], + ), + + VerticalSpacing(20), + + // Using responsive values based on screen size + Container( + width: SizeConfig.getResponsiveValue( + small: 150, + medium: 200, + large: 250, + ), + height: SizeConfig.height(60), + color: Colors.orange, + child: Center( + child: Text( + 'Responsive Width', + style: TextStyle(fontSize: SizeConfig.fontSize(14)), + ), + ), + ), + + VerticalSpacing(20), + + // Using padding and margin utilities + Container( + padding: SizeConfig.padding( + horizontal: 20, + vertical: 10, + ), + margin: SizeConfig.margin( + left: 10, + right: 10, + bottom: 10, + ), + decoration: BoxDecoration( + color: Colors.purple, + borderRadius: BorderRadius.circular(SizeConfig.width(8)), + ), + child: Text( + 'With Responsive Padding & Margin', + style: TextStyle( + fontSize: SizeConfig.fontSize(16), + color: Colors.white, + ), + ), + ), + ], + ), + ), + ); + } +} + +/// How to use in your main.dart or app initialization: +/// +/// void main() { +/// runApp(MyApp()); +/// } +/// +/// class MyApp extends StatelessWidget { +/// @override +/// Widget build(BuildContext context) { +/// return MaterialApp( +/// home: Builder( +/// builder: (context) { +/// // Initialize SizeConfig here +/// SizeConfig().init(context); +/// return YourMainScreen(); +/// }, +/// ), +/// ); +/// } +/// } \ No newline at end of file diff --git a/lib/app/modules/chat/userModule/authModule/views/chineseLoginScreen.dart b/lib/app/modules/chat/userModule/authModule/views/chineseLoginScreen.dart new file mode 100644 index 0000000..00aed12 --- /dev/null +++ b/lib/app/modules/chat/userModule/authModule/views/chineseLoginScreen.dart @@ -0,0 +1,460 @@ +import 'package:caller/app/modules/chat/MessageModule/views/messageChatViews/ChatHomePage.dart'; +import 'package:caller/app/modules/chat/userModule/authModule/controllers/loginController.dart'; +import 'package:caller/app/modules/chat/userModule/authModule/views/registerScreen.dart'; +import 'package:caller/app/modules/chat/userModule/authModule/views/chinesePhoneRegistration.dart'; +import 'package:caller/app/widgets/slider_test.dart'; +import 'package:caller/app/constants/size_config.dart'; +import 'package:caller/media-module/widget/svgicon.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:flutter/services.dart'; + +class ChineseLoginScreen extends StatefulWidget { + const ChineseLoginScreen({super.key}); + + @override + State createState() => _ChineseLoginScreenState(); +} + +class _ChineseLoginScreenState extends State { + // Controllers for form fields + final TextEditingController _userNameController = TextEditingController(); + final TextEditingController _passwordController = TextEditingController(); + + // Focus nodes + final FocusNode _userNameFocusNode = FocusNode(); + final FocusNode _passwordFocusNode = FocusNode(); + + // GetX controller - Initialize once in initState + late final LoginController _loginController; + + // Form key for validation + final _formKey = GlobalKey(); + + // Password visibility + bool _isPasswordVisible = false; + + // Carousel controller + final PageController _pageController = PageController(); + int _currentPage = 0; + + // Sample images for carousel (you can replace with actual images) + final List _carouselImages = [ + 'assets/images/3.0x/bsc.webp', + 'assets/images/3.0x/bsc.webp', + 'assets/images/3.0x/bsc.webp', + 'assets/images/3.0x/bsc.webp', + 'assets/images/3.0x/bsc.webp', + ]; + + @override + void initState() { + super.initState(); + // Initialize login controller once + _loginController = Get.put(LoginController()); + + // Initialize SizeConfig for responsive sizing + WidgetsBinding.instance.addPostFrameCallback((_) { + SizeConfig().init(context); + }); + } + + @override + void dispose() { + // Dispose controllers and focus nodes + _userNameController.dispose(); + _passwordController.dispose(); + _userNameFocusNode.dispose(); + _passwordFocusNode.dispose(); + _pageController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.black, + body: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0xFF1D304D), Color(0xFF1A1A1A), Color(0xFF1A1A1A)], + ), + ), + child: SafeArea( + child: SingleChildScrollView( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20), + child: Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + VerticalSpacing(20), + + // App Name - Siqxin + Center( + child: Text( + 'Siqxin', + style: TextStyle( + color: Colors.white, + fontSize: SizeConfig.fontSize(28), + fontWeight: FontWeight.bold, + ), + ), + ), + + VerticalSpacing(30), + + // Image Carousel + OnBoardingSlider(), + + // _buildImageCarousel(), + VerticalSpacing(40), + + // Sign In Title + Text( + 'Sign in', + style: TextStyle( + color: Colors.white, + fontSize: SizeConfig.fontSize(32), + fontWeight: FontWeight.bold, + ), + ), + + VerticalSpacing(8), + + // Create Account Text + RichText( + textAlign: TextAlign.center, + text: TextSpan( + style: TextStyle( + color: Colors.white70, + fontSize: SizeConfig.fontSize(16), + ), + children: [ + const TextSpan(text: "Don't have an account? "), + TextSpan( + text: 'Create account', + style: TextStyle( + color: Colors.white, + fontSize: SizeConfig.fontSize(16), + decoration: TextDecoration.underline, + ), + recognizer: TapGestureRecognizer() + ..onTap = () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + const ChinesePhoneRegistration(), + ), + ); + }, + ), + ], + ), + ), + + VerticalSpacing(40), + + // Username Field + _buildInputField( + controller: _userNameController, + focusNode: _userNameFocusNode, + hintText: 'Username', + keyboardType: TextInputType.text, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter your username'; + } + return null; + }, + ), + + // Password Field + _buildPasswordField(), + + VerticalSpacing(12), + + // Forgot Password Link + Align( + alignment: Alignment.centerRight, + child: TextButton( + onPressed: () { + // Navigate to forgot password screen + // Get.toNamed('/forgot-password'); + }, + style: TextButton.styleFrom( + padding: EdgeInsets.zero, + minimumSize: const Size(50, 30), + tapTargetSize: MaterialTapTargetSize.shrinkWrap, + ), + child: Text( + 'Forgot Password?', + style: TextStyle( + color: Colors.white70, + fontSize: SizeConfig.fontSize(14), + ), + ), + ), + ), + + const SizedBox(height: 40), + + // Sign In Button + _buildSignInButton(), + + // Error Message + _buildErrorMessage(), + ], + ), + ), + ), + ), + ), + ); + } + + // Image Carousel Widget + Widget _buildImageCarousel() { + return Column( + children: [ + // Image carousel + Container( + height: 200, + decoration: BoxDecoration(borderRadius: BorderRadius.circular(12)), + child: PageView.builder( + controller: _pageController, + onPageChanged: (index) { + setState(() { + _currentPage = index; + }); + }, + itemCount: _carouselImages.length, + itemBuilder: (context, index) { + return Container( + margin: const EdgeInsets.symmetric(horizontal: 8), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + image: DecorationImage( + image: AssetImage(_carouselImages[index]), + fit: BoxFit.cover, + ), + ), + ); + }, + ), + ), + + const SizedBox(height: 16), + + // Carousel indicators + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: List.generate( + _carouselImages.length, + (index) => Container( + width: 8, + height: 8, + margin: const EdgeInsets.symmetric(horizontal: 4), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: _currentPage == index ? Colors.white : Colors.white38, + ), + ), + ), + ), + ], + ); + } + + // Input field widget (Top Rounded) + Widget _buildInputField({ + required TextEditingController controller, + required FocusNode focusNode, + required String hintText, + TextInputType? keyboardType, + String? Function(String?)? validator, + }) { + return TextFormField( + controller: controller, + focusNode: focusNode, + style: const TextStyle(color: Colors.white), + keyboardType: keyboardType, + validator: validator, + decoration: InputDecoration( + hintText: hintText, + hintStyle: const TextStyle(color: Colors.white60), + filled: true, + fillColor: const Color(0xFF2A2A2A), + border: OutlineInputBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(SizeConfig.width(8)), // Only top rounded + bottom: Radius.zero, + ), + borderSide: BorderSide(color: Colors.grey), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(SizeConfig.width(8)), + bottom: Radius.zero, + ), + borderSide: BorderSide(color: Colors.grey), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(SizeConfig.width(8)), + bottom: Radius.zero, + ), + borderSide: BorderSide( + color: Colors.blue, + width: SizeConfig.width(1), + ), + ), + contentPadding: EdgeInsets.symmetric( + horizontal: SizeConfig.width(16), + vertical: SizeConfig.height(16), + ), + ), + ); + } + + // Password Field (Bottom Rounded) + Widget _buildPasswordField() { + return TextFormField( + controller: _passwordController, + focusNode: _passwordFocusNode, + style: const TextStyle(color: Colors.white), + obscureText: !_isPasswordVisible, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter your password'; + } + if (value.length < 6) { + return 'Password must be at least 6 characters'; + } + return null; + }, + decoration: InputDecoration( + hintText: 'Password', + hintStyle: const TextStyle(color: Colors.white60), + filled: true, + fillColor: const Color(0xFF2A2A2A), + border: OutlineInputBorder( + borderRadius: BorderRadius.vertical( + top: Radius.zero, + bottom: Radius.circular(SizeConfig.width(8)), // Only bottom rounded + ), + borderSide: BorderSide(color: Colors.grey), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.vertical( + top: Radius.zero, + bottom: Radius.circular(SizeConfig.width(8)), + ), + borderSide: BorderSide(color: Colors.grey), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.vertical( + top: Radius.zero, + bottom: Radius.circular(SizeConfig.width(8)), + ), + borderSide: BorderSide( + color: Colors.blue, + width: SizeConfig.width(1), + ), + ), + contentPadding: EdgeInsets.symmetric( + horizontal: SizeConfig.width(16), + vertical: SizeConfig.height(16), + ), + suffixIcon: TextButton( + onPressed: () { + setState(() { + _isPasswordVisible = !_isPasswordVisible; + }); + }, + child: Text( + _isPasswordVisible ? 'Hide' : 'Show', + style: const TextStyle(color: Colors.white70), + ), + ), + ), + ); + } + + // Sign In button widget + Widget _buildSignInButton() { + return Obx(() { + final isLoading = _loginController.isLoading; + + return SizedBox( + width: double.infinity, + child: ElevatedButton( + onPressed: isLoading ? null : _submitLogin, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + padding: const EdgeInsets.symmetric(vertical: 16), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + elevation: 0, + textStyle: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + ), + ), + child: isLoading + ? const SizedBox( + height: 20, + width: 20, + child: CircularProgressIndicator( + strokeWidth: 2, + valueColor: AlwaysStoppedAnimation(Colors.white), + ), + ) + : const Text('Sign in'), + ), + ); + }); + } + + // Error message widget + Widget _buildErrorMessage() { + return Obx(() { + final errorMessage = _loginController.errorMessage; + + return errorMessage.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(top: 12), + child: Text( + errorMessage, + style: const TextStyle( + color: Colors.redAccent, + fontSize: 14, + fontWeight: FontWeight.w500, + ), + textAlign: TextAlign.center, + ), + ) + : const SizedBox.shrink(); + }); + } + + // Submit login form + void _submitLogin() { + if (_formKey.currentState!.validate()) { + // Hide keyboard + FocusScope.of(context).unfocus(); + + // Call login method from controller + _loginController.login( + userName: _userNameController.text.trim(), + password: _passwordController.text.trim(), + ); + } + } +} diff --git a/lib/app/modules/chat/userModule/authModule/views/chinesePhoneRegistration.dart b/lib/app/modules/chat/userModule/authModule/views/chinesePhoneRegistration.dart new file mode 100644 index 0000000..c9f541d --- /dev/null +++ b/lib/app/modules/chat/userModule/authModule/views/chinesePhoneRegistration.dart @@ -0,0 +1,557 @@ +import 'package:caller/app/constants/size_config.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:caller/media-module/utils/size_config.dart'; +import 'package:flutter/services.dart'; +import 'package:caller/app/modules/chat/userModule/authModule/views/chineseRegistrationProfile.dart'; + +class ChinesePhoneRegistration extends StatefulWidget { + const ChinesePhoneRegistration({super.key}); + + @override + State createState() => + _ChinesePhoneRegistrationState(); +} + +class _ChinesePhoneRegistrationState extends State { + // Controllers for form fields + final TextEditingController _phoneController = TextEditingController(); + + // Focus nodes + final FocusNode _phoneFocusNode = FocusNode(); + + // Form key for validation + final _formKey = GlobalKey(); + + // Selected country + String _selectedCountry = 'China'; + + // List of countries + final List _countries = [ + 'China', + 'United States', + 'United Kingdom', + 'Canada', + 'Australia', + 'Germany', + 'France', + 'Japan', + 'South Korea', + 'India', + ]; + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + SizeConfig().init(context); + }); + } + + @override + void dispose() { + _phoneController.dispose(); + _phoneFocusNode.dispose(); + super.dispose(); + } + + void _showCountryPicker() { + showModalBottomSheet( + context: context, + backgroundColor: const Color(0xFF2A2A2A), + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(20)), + ), + builder: (context) => Container( + height: 300, + padding: const EdgeInsets.all(20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Select Country', + style: TextStyle( + color: Colors.white, + fontSize: SizeConfig.fontSize(18), + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 20), + Expanded( + child: ListView.builder( + itemCount: _countries.length, + itemBuilder: (context, index) { + final country = _countries[index]; + return ListTile( + title: Text( + country, + style: TextStyle( + color: Colors.white, + fontSize: SizeConfig.fontSize(16), + ), + ), + onTap: () { + setState(() { + _selectedCountry = country; + }); + Navigator.pop(context); + }, + trailing: _selectedCountry == country + ? Icon( + Icons.check, + color: Colors.blue, + size: SizeConfig.fontSize(20), + ) + : null, + ); + }, + ), + ), + ], + ), + ), + ); + } + + void _sendOTP() { + if (_formKey.currentState!.validate()) { + Get.snackbar( + 'Success', + 'OTP sent to $_selectedCountry ${_phoneController.text}', + backgroundColor: Colors.green, + colorText: Colors.white, + snackPosition: SnackPosition.TOP, + ); + + // Show OTP verification dialog + _showOTPVerificationDialog(); + } + } + + void _showOTPVerificationDialog() { + final List otpControllers = List.generate( + 6, + (index) => TextEditingController(), + ); + final List otpFocusNodes = List.generate( + 6, + (index) => FocusNode(), + ); + + showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return Dialog( + backgroundColor: Colors.transparent, + child: Container( + width: double.infinity, + padding: const EdgeInsets.all(7), + decoration: BoxDecoration( + gradient: const LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Color(0xFF1D304D), + Color(0xFF1A1A1A), + Color(0xFF1A1A1A), + ], + ), + borderRadius: BorderRadius.circular(20), + border: Border.all(color: Colors.grey.shade700), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Header with close button + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const SizedBox(width: 40), // Spacer for centering + Text( + 'OTP Verification', + style: TextStyle( + color: Colors.white, + fontSize: SizeConfig.fontSize(20), + fontWeight: FontWeight.bold, + ), + ), + GestureDetector( + onTap: () => Navigator.of(context).pop(), + child: Container( + width: 32, + height: 32, + decoration: BoxDecoration( + color: Colors.grey.shade800, + borderRadius: BorderRadius.circular(16), + ), + child: Icon( + Icons.close, + color: Colors.white, + size: SizeConfig.fontSize(18), + ), + ), + ), + ], + ), + + const SizedBox(height: 24), + + // Instructional text + Text( + 'Enter 6-digit code you received on your Phone number to verify your account', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: SizeConfig.fontSize(16), + height: 1.4, + ), + ), + + const SizedBox(height: 32), + + // OTP Input Fields + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: List.generate( + 6, + (index) => Container( + width: 35, + height: 45, + decoration: BoxDecoration( + color: const Color(0xFF2A2A2A), + borderRadius: BorderRadius.circular(8), + border: Border.all(color: Colors.grey.shade700), + ), + child: TextField( + controller: otpControllers[index], + focusNode: otpFocusNodes[index], + textAlign: TextAlign.center, + keyboardType: TextInputType.number, + maxLength: 1, + style: TextStyle( + color: Colors.white, + fontSize: SizeConfig.fontSize(20), + fontWeight: FontWeight.bold, + ), + decoration: const InputDecoration( + counterText: '', + border: InputBorder.none, + contentPadding: EdgeInsets.zero, + ), + onChanged: (value) { + if (value.length == 1 && index < 5) { + otpFocusNodes[index + 1].requestFocus(); + } else if (value.isEmpty && index > 0) { + otpFocusNodes[index - 1].requestFocus(); + } + }, + inputFormatters: [ + FilteringTextInputFormatter.digitsOnly, + ], + ), + ), + ), + ), + + const SizedBox(height: 32), + + // Resend OTP + GestureDetector( + onTap: () { + // TODO: Implement resend OTP logic + Get.snackbar( + 'OTP Resent', + 'New OTP has been sent to your phone', + backgroundColor: Colors.blue, + colorText: Colors.white, + snackPosition: SnackPosition.TOP, + ); + }, + child: Text( + 'Resend OTP', + style: TextStyle( + color: Colors.white, + fontSize: SizeConfig.fontSize(16), + decoration: TextDecoration.underline, + ), + ), + ), + + const SizedBox(height: 24), + + // Verify Button + SizedBox( + width: double.infinity, + height: 48, + child: ElevatedButton( + onPressed: () { + // TODO: Implement OTP verification logic + String otp = otpControllers + .map((controller) => controller.text) + .join(); + if (otp.length == 6) { + Get.snackbar( + 'Success', + 'OTP verified successfully!', + backgroundColor: Colors.green, + colorText: Colors.white, + snackPosition: SnackPosition.TOP, + ); + Navigator.of(context).pop(); + // Navigate to profile registration screen + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + const ChineseRegistrationProfile(), + ), + ); + } else { + Get.snackbar( + 'Error', + 'Please enter complete 6-digit OTP', + backgroundColor: Colors.red, + colorText: Colors.white, + snackPosition: SnackPosition.TOP, + ); + } + }, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + elevation: 0, + ), + child: Text( + 'Verify OTP', + style: TextStyle( + color: Colors.white, + fontSize: SizeConfig.fontSize(16), + fontWeight: FontWeight.w600, + ), + ), + ), + ), + ], + ), + ), + ); + }, + ).then((_) { + // Dispose controllers when dialog is closed + for (var controller in otpControllers) { + controller.dispose(); + } + for (var focusNode in otpFocusNodes) { + focusNode.dispose(); + } + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: const Color(0xFF1A1A1A), + resizeToAvoidBottomInset: true, + body: SafeArea( + child: Form( + key: _formKey, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 40), + + // App Name + Text( + 'Siqxin', + style: TextStyle( + color: Colors.blue, + fontSize: SizeConfig.fontSize(28), + fontWeight: FontWeight.bold, + ), + ), + + const SizedBox(height: 30), + + // Title + Text( + 'Create account', + style: TextStyle( + color: Colors.white, + fontSize: SizeConfig.fontSize(32), + fontWeight: FontWeight.bold, + ), + ), + + const SizedBox(height: 20), + + // Login prompt + Row( + children: [ + Text( + 'Already have an account? ', + style: TextStyle( + color: Colors.white, + fontSize: SizeConfig.fontSize(16), + ), + ), + GestureDetector( + onTap: () { + Get.back(); + }, + child: Text( + 'Log in', + style: TextStyle( + color: Colors.blue, + fontSize: SizeConfig.fontSize(16), + decoration: TextDecoration.underline, + ), + ), + ), + ], + ), + const SizedBox(height: 40), + + // Country Selection (Top rounded only) + Container( + width: double.infinity, + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 16, + ), + decoration: BoxDecoration( + color: const Color(0xFF2A2A2A), + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(12), + topRight: Radius.circular(12), + ), + border: Border.all(color: Colors.grey.shade700), + ), + child: GestureDetector( + onTap: _showCountryPicker, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + _selectedCountry, + style: TextStyle( + color: Colors.white, + fontSize: SizeConfig.fontSize(16), + ), + ), + Icon( + Icons.keyboard_arrow_down, + color: Colors.grey.shade400, + size: SizeConfig.fontSize(24), + ), + ], + ), + ), + ), + + // Phone Number Input (Bottom rounded only) + TextFormField( + controller: _phoneController, + focusNode: _phoneFocusNode, + keyboardType: TextInputType.phone, + style: TextStyle( + color: Colors.white, + fontSize: SizeConfig.fontSize(16), + ), + decoration: InputDecoration( + hintText: 'Telephone number', + hintStyle: TextStyle( + color: Colors.grey.shade400, + fontSize: SizeConfig.fontSize(16), + ), + filled: true, + fillColor: const Color(0xFF2A2A2A), + border: OutlineInputBorder( + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(12), + bottomRight: Radius.circular(12), + ), + borderSide: BorderSide(color: Colors.grey.shade700), + ), + enabledBorder: OutlineInputBorder( + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(12), + bottomRight: Radius.circular(12), + ), + borderSide: BorderSide(color: Colors.grey.shade700), + ), + focusedBorder: OutlineInputBorder( + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(12), + bottomRight: Radius.circular(12), + ), + borderSide: const BorderSide(color: Colors.blue), + ), + contentPadding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 16, + ), + ), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter your phone number'; + } + if (value.length < 10) { + return 'Please enter a valid phone number'; + } + return null; + }, + ), + + const SizedBox(height: 12), + + // Helper text + Text( + 'Enter the correct number, we will send an OTP to verify the number', + style: TextStyle( + color: Colors.grey.shade400, + fontSize: SizeConfig.fontSize(14), + ), + ), + + Spacer(), + + // Send OTP Button + SizedBox( + width: double.infinity, + height: 56, + child: ElevatedButton( + onPressed: _sendOTP, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + elevation: 0, + ), + child: Text( + 'Send OTP', + style: TextStyle( + color: Colors.white, + fontSize: SizeConfig.fontSize(18), + fontWeight: FontWeight.w600, + ), + ), + ), + ), + + const SizedBox(height: 20), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/app/modules/chat/userModule/authModule/views/chineseRegistrationProfile.dart b/lib/app/modules/chat/userModule/authModule/views/chineseRegistrationProfile.dart new file mode 100644 index 0000000..947ab3a --- /dev/null +++ b/lib/app/modules/chat/userModule/authModule/views/chineseRegistrationProfile.dart @@ -0,0 +1,407 @@ +import 'package:caller/app/constants/size_config.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:caller/media-module/utils/size_config.dart'; +import 'package:flutter/services.dart'; + +class ChineseRegistrationProfile extends StatefulWidget { + const ChineseRegistrationProfile({super.key}); + + @override + State createState() => + _ChineseRegistrationProfileState(); +} + +class _ChineseRegistrationProfileState + extends State { + final TextEditingController _fullNameController = TextEditingController(); + final TextEditingController _dateOfBirthController = TextEditingController(); + final TextEditingController _passwordController = TextEditingController(); + + final FocusNode _fullNameFocusNode = FocusNode(); + final FocusNode _dateOfBirthFocusNode = FocusNode(); + final FocusNode _passwordFocusNode = FocusNode(); + + final _formKey = GlobalKey(); + + bool _showPassword = false; + bool _acceptTerms = false; + DateTime? _selectedDate; + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + SizeConfig().init(context); + }); + } + + @override + void dispose() { + _fullNameController.dispose(); + _dateOfBirthController.dispose(); + _passwordController.dispose(); + _fullNameFocusNode.dispose(); + _dateOfBirthFocusNode.dispose(); + _passwordFocusNode.dispose(); + super.dispose(); + } + + void _showDatePicker() { + showDatePicker( + context: context, + initialDate: DateTime.now().subtract(const Duration(days: 6570)), + firstDate: DateTime(1900), + lastDate: DateTime.now().subtract(const Duration(days: 6570)), + builder: (context, child) { + return Theme( + data: Theme.of(context).copyWith( + colorScheme: const ColorScheme.dark( + primary: Colors.blue, + onPrimary: Colors.white, + surface: Color(0xFF2A2A2A), + onSurface: Colors.white, + ), + dialogBackgroundColor: const Color(0xFF1A1A1A), + ), + child: child!, + ); + }, + ).then((date) { + if (date != null) { + setState(() { + _selectedDate = date; + _dateOfBirthController.text = + "${date.day}/${date.month}/${date.year}"; + }); + } + }); + } + + void _showTermsAndConditions() { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + backgroundColor: const Color(0xFF2A2A2A), + title: Text( + 'General Terms & Conditions', + style: TextStyle( + color: Colors.white, + fontSize: SizeConfig.fontSize(18), + fontWeight: FontWeight.bold, + ), + ), + content: SingleChildScrollView( + child: Text( + 'By using this application, you agree to the following terms and conditions:\n\n' + '1. You must be at least 18 years old to use this service.\n' + '2. You are responsible for maintaining the confidentiality of your account.\n' + '3. You agree not to use the service for any illegal purposes.\n' + '4. We reserve the right to modify these terms at any time.\n' + '5. Your personal information will be handled according to our privacy policy.', + style: TextStyle( + color: Colors.white, + fontSize: SizeConfig.fontSize(14), + ), + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: Text( + 'Close', + style: TextStyle( + color: Colors.blue, + fontSize: SizeConfig.fontSize(16), + ), + ), + ), + ], + ); + }, + ); + } + + void _agreeAndContinue() { + if (_formKey.currentState!.validate() && _acceptTerms) { + Get.snackbar( + 'Success', + 'Account created successfully!', + backgroundColor: Colors.green, + colorText: Colors.white, + snackPosition: SnackPosition.TOP, + ); + } else if (!_acceptTerms) { + Get.snackbar( + 'Error', + 'Please accept the terms and conditions', + backgroundColor: Colors.red, + colorText: Colors.white, + snackPosition: SnackPosition.TOP, + ); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: const Color(0xFF1A1A1A), + resizeToAvoidBottomInset: true, + body: SafeArea( + child: SingleChildScrollView( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + child: Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 20), + Text( + 'Create account', + style: TextStyle( + color: Colors.white, + fontSize: SizeConfig.fontSize(32), + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 12), + Row( + children: [ + Text( + 'Already have an account? ', + style: TextStyle( + color: Colors.white, + fontSize: SizeConfig.fontSize(16), + ), + ), + GestureDetector( + onTap: () { + Get.back(); + }, + child: Text( + 'Log in', + style: TextStyle( + color: Colors.blue, + fontSize: SizeConfig.fontSize(16), + decoration: TextDecoration.underline, + ), + ), + ), + ], + ), + const SizedBox(height: 40), + TextFormField( + controller: _fullNameController, + focusNode: _fullNameFocusNode, + keyboardType: TextInputType.name, + style: TextStyle( + color: Colors.white, + fontSize: SizeConfig.fontSize(16), + ), + decoration: InputDecoration( + hintText: 'Enter full name', + hintStyle: TextStyle( + color: Colors.grey.shade400, + fontSize: SizeConfig.fontSize(16), + ), + filled: true, + fillColor: const Color(0xFF2A2A2A), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide(color: Colors.grey.shade700), + ), + ), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter your full name'; + } + if (value.length < 2) { + return 'Name must be at least 2 characters'; + } + return null; + }, + ), + const SizedBox(height: 8), + Text( + 'The name must match with your ID', + style: TextStyle( + color: Colors.grey.shade400, + fontSize: SizeConfig.fontSize(14), + ), + ), + const SizedBox(height: 20), + GestureDetector( + onTap: _showDatePicker, + child: Container( + width: double.infinity, + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 16, + ), + decoration: BoxDecoration( + color: const Color(0xFF2A2A2A), + borderRadius: BorderRadius.circular(12), + border: Border.all(color: Colors.grey.shade700), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + _dateOfBirthController.text.isEmpty + ? 'Date of birth' + : _dateOfBirthController.text, + style: TextStyle( + color: _dateOfBirthController.text.isEmpty + ? Colors.grey.shade400 + : Colors.white, + fontSize: SizeConfig.fontSize(16), + ), + ), + Icon( + Icons.keyboard_arrow_down, + color: Colors.grey.shade400, + ), + ], + ), + ), + ), + const SizedBox(height: 8), + Text( + 'The minimum age for registration is 18 years old', + style: TextStyle( + color: Colors.grey.shade400, + fontSize: SizeConfig.fontSize(14), + ), + ), + const SizedBox(height: 20), + TextFormField( + controller: _passwordController, + focusNode: _passwordFocusNode, + obscureText: !_showPassword, + style: TextStyle( + color: Colors.white, + fontSize: SizeConfig.fontSize(16), + ), + decoration: InputDecoration( + hintText: 'Password', + hintStyle: TextStyle( + color: Colors.grey.shade400, + fontSize: SizeConfig.fontSize(16), + ), + filled: true, + fillColor: const Color(0xFF2A2A2A), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide(color: Colors.grey.shade700), + ), + suffixIcon: TextButton( + onPressed: () { + setState(() { + _showPassword = !_showPassword; + }); + }, + child: Text( + _showPassword ? 'Hide' : 'Show', + style: TextStyle(color: Colors.white), + ), + ), + ), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter a password'; + } + if (value.length < 8) { + return 'Password must be at least 8 characters'; + } + if (value.toLowerCase().contains( + _fullNameController.text.toLowerCase(), + )) { + return 'Password cannot include your name'; + } + return null; + }, + ), + const SizedBox(height: 8), + Text( + 'Password must be at least 8 characters. Can\'t include your name or email address', + style: TextStyle( + color: Colors.grey.shade400, + fontSize: SizeConfig.fontSize(14), + ), + ), + + const SizedBox(height: 80), // Space for button + ], + ), + ), + ), + ), + + bottomNavigationBar: Container( + color: const Color(0xFF1A1A1A), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // I confirm text + RichText( + text: TextSpan( + style: TextStyle( + color: Colors.white, + fontSize: SizeConfig.fontSize(14), + ), + children: [ + const TextSpan( + text: + 'I confirm that I am at least 18 years of age, and accept the ', + ), + WidgetSpan( + child: GestureDetector( + onTap: _showTermsAndConditions, + child: Text( + 'General Terms & Conditions', + style: TextStyle( + color: Colors.blue, + fontSize: SizeConfig.fontSize(14), + decoration: TextDecoration.underline, + ), + ), + ), + ), + ], + ), + ), + const SizedBox(height: 12), + + // Agree and continue button + SizedBox( + width: double.infinity, + height: 56, + child: ElevatedButton( + onPressed: _agreeAndContinue, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + elevation: 0, + ), + child: Text( + 'Agree and continue', + style: TextStyle( + color: Colors.white, + fontSize: SizeConfig.fontSize(18), + fontWeight: FontWeight.w600, + ), + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/chat/userModule/authModule/views/loginScreen.dart b/lib/app/modules/chat/userModule/authModule/views/loginScreen.dart index 622e45e..71af468 100644 --- a/lib/app/modules/chat/userModule/authModule/views/loginScreen.dart +++ b/lib/app/modules/chat/userModule/authModule/views/loginScreen.dart @@ -1,6 +1,9 @@ import 'package:caller/app/modules/chat/MessageModule/views/messageChatViews/ChatHomePage.dart'; import 'package:caller/app/modules/chat/userModule/authModule/controllers/loginController.dart'; import 'package:caller/app/modules/chat/userModule/authModule/views/registerScreen.dart'; +import 'package:caller/media-module/utils/size_config.dart'; +import 'package:caller/media-module/widget/svgicon.dart'; +import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:flutter/services.dart'; @@ -27,15 +30,8 @@ class _LoginScreenState extends State { // Form key for validation final _formKey = GlobalKey(); - // Styling constants (matching registration screen) - final _borderRadius = BorderRadius.circular(12.0); - final _boxShadow = [ - const BoxShadow( - color: Colors.black12, - blurRadius: 4, - offset: Offset(0, 2), - ) - ]; + // Password visibility + bool _isPasswordVisible = false; @override void initState() { @@ -57,202 +53,318 @@ class _LoginScreenState extends State { @override Widget build(BuildContext context) { return Scaffold( - resizeToAvoidBottomInset: true, - appBar: AppBar( - title: const Text('Sign In'), - centerTitle: true, - elevation: 0, - backgroundColor: Colors.transparent, - foregroundColor: Theme.of(context).primaryColor, - ), - body: SingleChildScrollView( - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 40), - child: Form( - key: _formKey, - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - // Card container for form with shadow (matching registration) - Card( - elevation: 4, - shape: RoundedRectangleBorder( - borderRadius: _borderRadius, - ), - child: Padding( - padding: const EdgeInsets.all(20.0), - child: Column( + body: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0xFF1D304D), Color(0xFF1A1A1A), Color(0xFF1A1A1A)], + ), + ), + child: SafeArea( + child: SingleChildScrollView( + padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 40), + child: Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 40), + + // Title Section + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, children: [ - // Username Field - _buildTextFormField( - controller: _userNameController, - focusNode: _userNameFocusNode, - labelText: 'Username', - prefixIcon: Icons.person_rounded, - keyboardType: TextInputType.text, - validator: (value) { - if (value == null || value.isEmpty) { - return 'Please enter your username'; - } - return null; - }, - ), - const SizedBox(height: 18), - - // Password Field - _buildTextFormField( - controller: _passwordController, - focusNode: _passwordFocusNode, - labelText: 'Password', - prefixIcon: Icons.lock_rounded, - obscureText: true, - validator: (value) { - if (value == null || value.isEmpty) { - return 'Please enter your password'; - } - if (value.length < 6) { - return 'Password must be at least 6 characters'; - } - return null; - }, - ), - const SizedBox(height: 12), - - // Forgot Password Link - Align( - alignment: Alignment.centerRight, - child: TextButton( - onPressed: () { - // Navigate to forgot password screen - // Get.toNamed('/forgot-password'); - }, - style: TextButton.styleFrom( - padding: EdgeInsets.zero, - minimumSize: const Size(50, 30), - tapTargetSize: MaterialTapTargetSize.shrinkWrap, - ), - child: Text( - 'Forgot Password?', - style: TextStyle( - color: Theme.of(context).primaryColor, - fontSize: 14, - ), - ), + const Text( + 'Sign In', + style: TextStyle( + color: Colors.white, + fontSize: 32, + fontWeight: FontWeight.bold, ), ), - const SizedBox(height: 24), - - // Login Button - _buildLoginButton(), - - // Error Message - _buildErrorMessage(), - - const SizedBox(height: 20), - - // Register Link - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text("Don't have an account?"), - TextButton( - onPressed: () { - // Navigate to registration screen - Get.to(RegisterScreen()); - }, - style: TextButton.styleFrom( - padding: const EdgeInsets.symmetric(horizontal: 8), - tapTargetSize: MaterialTapTargetSize.shrinkWrap, - ), - child: Text( - 'Sign Up', - style: TextStyle( - color: Theme.of(context).primaryColor, - fontWeight: FontWeight.w600, - ), - ), + const SizedBox(height: 8), + RichText( + textAlign: TextAlign.center, + text: TextSpan( + style: const TextStyle( + color: Colors.white70, + fontSize: 16, ), - ], + children: [ + const TextSpan(text: 'Sign in to your account or '), + TextSpan( + text: 'create an account', + style: const TextStyle( + color: Colors.white, + fontSize: 16, + decoration: TextDecoration.underline, + ), + recognizer: TapGestureRecognizer() + ..onTap = () { + // Registration screen par navigate karein + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + const RegisterScreen(), + ), + ); + }, + ), + const TextSpan(text: '.'), + ], + ), ), ], ), - ), + + const SizedBox(height: 40), + + // Username Field + _buildInputField( + controller: _userNameController, + focusNode: _userNameFocusNode, + hintText: 'Username', + keyboardType: TextInputType.text, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter your username'; + } + return null; + }, + ), + + // const SizedBox(height: 16), + + // Password Field + _buildPasswordField(), + + const SizedBox(height: 12), + + // Forgot Password Link + Align( + alignment: Alignment.centerRight, + child: TextButton( + onPressed: () { + // Navigate to forgot password screen + // Get.toNamed('/forgot-password'); + }, + style: TextButton.styleFrom( + padding: EdgeInsets.zero, + minimumSize: const Size(50, 30), + tapTargetSize: MaterialTapTargetSize.shrinkWrap, + ), + child: const Text( + 'Forgot Password?', + style: TextStyle(color: Colors.white, fontSize: 14), + ), + ), + ), + + const SizedBox(height: 24), + + // Sign In Button + _buildSignInButton(), + + const SizedBox(height: 32), + + // Or Divider + Row( + children: [ + Expanded( + child: Container(height: 1, color: Colors.white24), + ), + const Padding( + padding: EdgeInsets.symmetric(horizontal: 16), + child: Text( + 'Or', + style: TextStyle(color: Colors.white70, fontSize: 14), + ), + ), + Expanded( + child: Container(height: 1, color: Colors.white24), + ), + ], + ), + + const SizedBox(height: 24), + + // Social Login Buttons + _buildSocialLoginButton( + icon: 'assets/icons/google.svg', + text: 'Continue with Google', + onPressed: () { + // Handle Google login + }, + ), + + const SizedBox(height: 12), + + _buildSocialLoginButton( + icon: 'assets/icons/x.svg', + text: 'Continue with Facebook', + onPressed: () { + // Handle Facebook login + }, + ), + + const SizedBox(height: 12), + + _buildSocialLoginButton( + icon: 'assets/icons/facebook.svg', + text: 'Continue with Twitter', + onPressed: () { + // Handle Apple login + }, + ), + + const SizedBox(height: 24), + + // Show more options button + _buildShowMoreOptionsButton(), + + // Error Message + _buildErrorMessage(), + ], ), - ], + ), ), ), ), ); } - // Reusable TextFormField helper (same as registration) - Widget _buildTextFormField({ + // Input field widget + // Generic Input Field (Top Rounded) + Widget _buildInputField({ required TextEditingController controller, required FocusNode focusNode, - required String labelText, - required IconData prefixIcon, + required String hintText, TextInputType? keyboardType, - List? inputFormatters, String? Function(String?)? validator, - bool obscureText = false, }) { return TextFormField( - style: TextStyle(color: Theme.of(context).textTheme.bodyMedium!.color), - focusNode: focusNode, controller: controller, + focusNode: focusNode, + style: const TextStyle(color: Colors.white), + keyboardType: keyboardType, + validator: validator, decoration: InputDecoration( - labelStyle: TextStyle(color: Theme.of(context).textTheme.bodyMedium!.color), - labelText: labelText, - prefixIcon: Icon(prefixIcon), + hintText: hintText, + hintStyle: const TextStyle(color: Colors.white60), + filled: true, + fillColor: const Color(0xFF2A2A2A), border: OutlineInputBorder( - borderRadius: _borderRadius, + borderRadius: const BorderRadius.vertical( + top: Radius.circular(8), // Only top rounded + bottom: Radius.zero, + ), + borderSide: const BorderSide( + color: Colors.grey, + ), // Inactive border grey + ), + enabledBorder: OutlineInputBorder( + borderRadius: const BorderRadius.vertical( + top: Radius.circular(8), + bottom: Radius.zero, + ), borderSide: const BorderSide(color: Colors.grey), ), focusedBorder: OutlineInputBorder( - borderRadius: _borderRadius, - borderSide: BorderSide( - color: Theme.of(context).primaryColor, - width: 2, + borderRadius: const BorderRadius.vertical( + top: Radius.circular(8), + bottom: Radius.zero, ), + borderSide: const BorderSide(color: Colors.blue, width: 1), + ), + contentPadding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 16, ), - filled: true, - fillColor: Colors.grey[50], ), - keyboardType: keyboardType, - inputFormatters: inputFormatters, - obscureText: obscureText, - validator: validator, - textInputAction: obscureText - ? TextInputAction.done - : TextInputAction.next, - onFieldSubmitted: (value) { - // Navigate focus to next field - if (obscureText) { - _passwordFocusNode.unfocus(); - } else { - FocusScope.of(context).requestFocus(_passwordFocusNode); - } - }, ); } - // Login button widget (matching registration button style) - Widget _buildLoginButton() { + // Password Field (Bottom Rounded) + Widget _buildPasswordField() { + return TextFormField( + controller: _passwordController, + focusNode: _passwordFocusNode, + style: const TextStyle(color: Colors.white), + obscureText: !_isPasswordVisible, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter your password'; + } + if (value.length < 6) { + return 'Password must be at least 6 characters'; + } + return null; + }, + decoration: InputDecoration( + hintText: 'Password', + hintStyle: const TextStyle(color: Colors.white60), + filled: true, + fillColor: const Color(0xFF2A2A2A), + border: OutlineInputBorder( + borderRadius: const BorderRadius.vertical( + top: Radius.zero, + bottom: Radius.circular(8), // Only bottom rounded + ), + borderSide: const BorderSide(color: Colors.grey), + ), + enabledBorder: OutlineInputBorder( + borderRadius: const BorderRadius.vertical( + top: Radius.zero, + bottom: Radius.circular(8), + ), + borderSide: const BorderSide(color: Colors.grey), + ), + focusedBorder: OutlineInputBorder( + borderRadius: const BorderRadius.vertical( + top: Radius.zero, + bottom: Radius.circular(8), + ), + borderSide: const BorderSide(color: Colors.blue, width: 1), + ), + contentPadding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 16, + ), + suffixIcon: TextButton( + onPressed: () { + setState(() { + _isPasswordVisible = !_isPasswordVisible; + }); + }, + child: Text( + _isPasswordVisible ? 'Hide' : 'Show', + style: const TextStyle(color: Colors.white), + ), + ), + ), + ); + } + + // Sign In button widget + Widget _buildSignInButton() { return Obx(() { final isLoading = _loginController.isLoading; - + return SizedBox( width: double.infinity, child: ElevatedButton( onPressed: isLoading ? null : _submitLogin, style: ElevatedButton.styleFrom( - backgroundColor: Theme.of(context).primaryColor, + backgroundColor: Colors.blue, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder( - borderRadius: _borderRadius, + borderRadius: BorderRadius.circular(8), ), - elevation: 4, + elevation: 0, textStyle: const TextStyle( fontSize: 16, fontWeight: FontWeight.w600, @@ -273,11 +385,110 @@ class _LoginScreenState extends State { }); } - // Error message widget (matching registration) + // Social login button widget + Widget _buildSocialLoginButton({ + required String icon, + required String text, + required VoidCallback onPressed, + }) { + return SizedBox( + width: double.infinity, + child: OutlinedButton( + onPressed: onPressed, + style: OutlinedButton.styleFrom( + backgroundColor: const Color(0xFF2A2A2A), + foregroundColor: Colors.white, + padding: const EdgeInsets.symmetric(vertical: 16), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + side: const BorderSide(color: Colors.white24), + ), + child: Stack( + alignment: Alignment.center, + children: [ + Align( + alignment: Alignment.centerLeft, + child: Padding( + padding: const EdgeInsets.only(left: 12), + child: _buildSocialIcon(icon), // Icon left side + ), + ), + Center( + child: Text( + text, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + ), + ), + ), + ], + ), + ), + ); + } + + // Social icon widget + Widget _buildSocialIcon(String iconPath) { + // For now, using simple icons. You can replace with actual SVG icons + switch (iconPath) { + case 'assets/icons/google.svg': + // iconData = Icons.g_mobiledata; // Placeholder for Google + break; + case 'assets/icons/facebook.svg': + // iconData = Icons.facebook; // Placeholder for Facebook + break; + case 'assets/icons/x.svg': + // iconData = Icons.apple; // Placeholder for Apple + break; + default: + // iconData = Icons.account_circle; + } + + return SvgIcon(iconPath, height: SizeUtils.fontSize(28)); + } + + // Show more options button + Widget _buildShowMoreOptionsButton() { + return SizedBox( + width: double.infinity, + child: OutlinedButton( + onPressed: () { + // Handle show more options + }, + style: OutlinedButton.styleFrom( + backgroundColor: const Color(0xFF2A2A2A), + foregroundColor: Colors.white, + padding: const EdgeInsets.symmetric(vertical: 16), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + side: const BorderSide(color: Colors.white24), + ), + child: Stack( + alignment: Alignment.center, + children: [ + const Align( + alignment: Alignment.centerLeft, + child: Padding( + padding: EdgeInsets.only(left: 12), // Icon thoda andar + child: Icon(Icons.add, size: 24), + ), + ), + const Center( + child: Text( + 'Show more options', + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500), + ), + ), + ], + ), + ), + ); + } + + // Error message widget Widget _buildErrorMessage() { return Obx(() { final errorMessage = _loginController.errorMessage; - + return errorMessage.isNotEmpty ? Padding( padding: const EdgeInsets.only(top: 12), @@ -300,7 +511,7 @@ class _LoginScreenState extends State { if (_formKey.currentState!.validate()) { // Hide keyboard FocusScope.of(context).unfocus(); - + // Call login method from controller _loginController.login( userName: _userNameController.text.trim(), @@ -308,4 +519,4 @@ class _LoginScreenState extends State { ); } } -} \ No newline at end of file +} diff --git a/lib/app/modules/chat/userModule/authModule/views/registerScreen.dart b/lib/app/modules/chat/userModule/authModule/views/registerScreen.dart index 4c97503..ea23216 100644 --- a/lib/app/modules/chat/userModule/authModule/views/registerScreen.dart +++ b/lib/app/modules/chat/userModule/authModule/views/registerScreen.dart @@ -2,6 +2,8 @@ import 'package:caller/app/modules/chat/MessageModule/views/messageChatViews/Cha import 'package:caller/app/modules/chat/userModule/areaModule/controllers/areaController.dart'; import 'package:caller/app/modules/chat/userModule/authModule/controllers/registerController.dart'; import 'package:caller/app/modules/chat/userModule/authModule/views/loginSCreen.dart'; +import 'package:caller/media-module/utils/size_config.dart'; +import 'package:caller/media-module/widget/svgicon.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:flutter/services.dart'; @@ -15,15 +17,19 @@ class RegisterScreen extends StatefulWidget { class _RegisterScreenState extends State { // Controllers for form fields - final TextEditingController _nameController = TextEditingController(); - final TextEditingController _ageController = TextEditingController(); - final TextEditingController _mobileController = TextEditingController(); + final TextEditingController _usernameController = TextEditingController(); + final TextEditingController _emailController = TextEditingController(); + final TextEditingController _dateOfBirthController = TextEditingController(); final TextEditingController _passwordController = TextEditingController(); + final TextEditingController _countryController = TextEditingController(); + final TextEditingController _telephoneController = TextEditingController(); - final FocusNode _nameFocusNode = FocusNode(); - final FocusNode _ageFocusNode = FocusNode(); - final FocusNode _mobileFocusNode = FocusNode(); + final FocusNode _usernameFocusNode = FocusNode(); + final FocusNode _emailFocusNode = FocusNode(); + final FocusNode _dateOfBirthFocusNode = FocusNode(); final FocusNode _passwordFocusNode = FocusNode(); + final FocusNode _countryFocusNode = FocusNode(); + final FocusNode _telephoneFocusNode = FocusNode(); // GetX controllers - Initialize once in initState late final RegisterController _registerViewModel; @@ -32,11 +38,10 @@ class _RegisterScreenState extends State { // Form key for validation final _formKey = GlobalKey(); - // Styling constants - final _borderRadius = BorderRadius.circular(12.0); - final _boxShadow = [ - const BoxShadow(color: Colors.black12, blurRadius: 4, offset: Offset(0, 2)), - ]; + // UI state + bool _showPassword = false; + bool _acceptTerms = false; + DateTime? _selectedDate; @override void initState() { @@ -56,15 +61,19 @@ class _RegisterScreenState extends State { @override void dispose() { // Dispose controllers and focus nodes - _nameController.dispose(); - _ageController.dispose(); - _mobileController.dispose(); + _usernameController.dispose(); + _emailController.dispose(); + _dateOfBirthController.dispose(); _passwordController.dispose(); + _countryController.dispose(); + _telephoneController.dispose(); - _nameFocusNode.dispose(); - _ageFocusNode.dispose(); - _mobileFocusNode.dispose(); + _usernameFocusNode.dispose(); + _emailFocusNode.dispose(); + _dateOfBirthFocusNode.dispose(); _passwordFocusNode.dispose(); + _countryFocusNode.dispose(); + _telephoneFocusNode.dispose(); super.dispose(); } @@ -72,314 +81,481 @@ class _RegisterScreenState extends State { @override Widget build(BuildContext context) { return Scaffold( - resizeToAvoidBottomInset: true, - appBar: AppBar( - title: const Text('Create Account'), - centerTitle: true, - elevation: 0, - backgroundColor: Colors.transparent, - foregroundColor: Theme.of(context).primaryColor, - ), - body: SingleChildScrollView( - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), - child: Form( - key: _formKey, - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - // Card container for form with shadow - Card( - elevation: 4, - shape: RoundedRectangleBorder(borderRadius: _borderRadius), - child: Padding( - padding: const EdgeInsets.all(20.0), - child: Column( + body: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0xFF1D304D), Color(0xFF1A1A1A), Color(0xFF1A1A1A)], + ), + ), + child: SafeArea( + child: SingleChildScrollView( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + child: Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 40), + + // Title + const Text( + 'Create account', + style: TextStyle( + fontSize: 32, + fontWeight: FontWeight.bold, + color: Colors.white, + ), + textAlign: TextAlign.center, + ), + + const SizedBox(height: 8), + + // Login link + Row( + mainAxisAlignment: MainAxisAlignment.start, children: [ - // Name Field - _buildTextFormField( - controller: _nameController, - focusNode: _nameFocusNode, - labelText: 'Full Name', - prefixIcon: Icons.person_rounded, - validator: (value) { - if (value == null || value.isEmpty) { - return 'Please enter your name'; - } - return null; - }, + const Text( + 'Already have an account? ', + style: TextStyle(fontSize: 16, color: Colors.white70), ), - const SizedBox(height: 18), - - // Gender Selection with Styled Switch - _buildGenderSelector(), - const SizedBox(height: 18), - - // Age Field - _buildTextFormField( - controller: _ageController, - focusNode: _ageFocusNode, - labelText: 'Age', - prefixIcon: Icons.calendar_today_rounded, - keyboardType: TextInputType.number, - inputFormatters: [ - FilteringTextInputFormatter.digitsOnly, - ], - validator: (value) { - if (value == null || value.isEmpty) { - return 'Please enter your age'; - } - final age = int.tryParse(value); - if (age == null || age <= 0 || age > 120) { - return 'Enter a valid age (1-120)'; - } - return null; - }, + GestureDetector( + onTap: () => Get.to(() => LoginScreen()), + child: const Text( + 'Log in', + style: const TextStyle( + color: Colors.white, + fontSize: 16, + decoration: TextDecoration.underline, + decorationColor: Colors.white, + ), + ), ), - const SizedBox(height: 18), - - // Mobile Number + Area Code Row - _buildMobileNumberRow(), - const SizedBox(height: 18), - - // Password Field - _buildTextFormField( - controller: _passwordController, - focusNode: _passwordFocusNode, - labelText: 'Password', - prefixIcon: Icons.lock_rounded, - obscureText: true, - validator: (value) { - if (value == null || value.isEmpty) { - return 'Create a password'; - } - if (value.length < 6) { - return 'Password must be ≥6 characters'; - } - return null; - }, - ), - const SizedBox(height: 24), - - // Register Button - _buildRegisterButton(), - - // Error Message - _buildErrorMessage(), ], ), - ), + + const SizedBox(height: 20), + + // Username Field - Top rounded corners only + _buildInputField( + controller: _usernameController, + focusNode: _usernameFocusNode, + label: 'Username', + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(12), + topRight: Radius.circular(12), + bottomLeft: Radius.zero, + bottomRight: Radius.zero, + ), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter username'; + } + return null; + }, + ), + + // Email Field - Bottom rounded corners only + _buildInputField( + controller: _emailController, + focusNode: _emailFocusNode, + label: 'Email', + keyboardType: TextInputType.emailAddress, + borderRadius: const BorderRadius.only( + topLeft: Radius.zero, + topRight: Radius.zero, + bottomLeft: Radius.circular(12), + bottomRight: Radius.circular(12), + ), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter email'; + } + if (!GetUtils.isEmail(value)) { + return 'Please enter valid email'; + } + return null; + }, + ), + + const SizedBox(height: 8), + + // Note about name matching ID + const Padding( + padding: EdgeInsets.only(left: 16), + child: Text( + 'The name must match the details on the ID.', + style: TextStyle(fontSize: 12, color: Colors.white54), + ), + ), + + const SizedBox(height: 24), + + // Date of Birth Field + _buildDateOfBirthField(), + + const SizedBox(height: 8), + + // Age requirement note + const Padding( + padding: EdgeInsets.only(left: 16), + child: Text( + 'The minimum age for registration is 18 years old.', + style: TextStyle(fontSize: 12, color: Colors.white54), + ), + ), + + const SizedBox(height: 16), + + // Password Field + _buildPasswordField(), + + const SizedBox(height: 8), + + // Password requirements note + const Padding( + padding: EdgeInsets.only(left: 16), + child: Text( + 'Password must be at least 8 characters. Can\'t include your name or email address.', + style: TextStyle(fontSize: 12, color: Colors.white54), + ), + ), + + const SizedBox(height: 24), + + // Country Field - Top rounded corners only + _buildInputField( + controller: _countryController, + focusNode: _countryFocusNode, + label: 'Country', + suffixIcon: Icons.keyboard_arrow_down, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(12), + topRight: Radius.circular(12), + bottomLeft: Radius.zero, + bottomRight: Radius.zero, + ), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please select country'; + } + return null; + }, + ), + + // Telephone Field - Bottom rounded corners only + _buildInputField( + controller: _telephoneController, + focusNode: _telephoneFocusNode, + label: 'Telephone number', + keyboardType: TextInputType.phone, + borderRadius: const BorderRadius.only( + topLeft: Radius.zero, + topRight: Radius.zero, + bottomLeft: Radius.circular(12), + bottomRight: Radius.circular(12), + ), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter telephone number'; + } + return null; + }, + ), + + const SizedBox(height: 24), + + // Terms and Conditions + _buildTermsAndConditions(), + + const SizedBox(height: 32), + + // Agree and Continue Button + _buildAgreeButton(), + + const SizedBox(height: 24), + + // Or separator + const Row( + children: [ + Expanded(child: Divider(color: Colors.white24)), + Padding( + padding: EdgeInsets.symmetric(horizontal: 16), + child: Text( + 'Or', + style: TextStyle(color: Colors.white54, fontSize: 16), + ), + ), + Expanded(child: Divider(color: Colors.white24)), + ], + ), + + const SizedBox(height: 24), + + // Social Media Buttons + _buildSocialButton( + icon: 'assets/icons/google.svg', + text: 'Continue with Google', + backgroundColor: Colors.white, + textColor: Colors.black87, + onTap: () { + // Handle Google login + }, + ), + + const SizedBox(height: 12), + + _buildSocialButton( + icon: 'assets/icons/x.svg', + text: 'Continue with Facebook', + backgroundColor: const Color(0xFF1877F2), + textColor: Colors.white, + onTap: () { + // Handle Facebook login + }, + ), + + const SizedBox(height: 12), + + _buildSocialButton( + icon: 'assets/icons/facebook.svg', + text: 'Continue with Twitter', + backgroundColor: Colors.black, + textColor: Colors.white, + onTap: () { + // Handle Twitter login + }, + ), + + const SizedBox(height: 12), + + _buildSocialButton( + icon: '+', + text: 'Show more options', + backgroundColor: Colors.transparent, + textColor: Colors.white, + borderColor: Colors.white24, + onTap: () { + // Handle more options + }, + ), + + const SizedBox(height: 40), + ], ), - ], - ), - ), - ), - ); - } - - // Helper method to build consistent TextFormField - Widget _buildTextFormField({ - required TextEditingController controller, - required FocusNode focusNode, - required String labelText, - required IconData prefixIcon, - TextInputType? keyboardType, - List? inputFormatters, - String? Function(String?)? validator, - bool obscureText = false, - }) { - return TextFormField( - style: TextStyle(color:Theme.of(context).textTheme.bodyMedium!.color,), - - focusNode: focusNode, - controller: controller, - decoration: InputDecoration( - labelStyle: TextStyle(color: Theme.of(context).textTheme.bodyMedium!.color,), - labelText: labelText, - prefixIcon: Icon(prefixIcon), - border: OutlineInputBorder( - borderRadius: _borderRadius, - borderSide: const BorderSide(color: Colors.grey), - ), - focusedBorder: OutlineInputBorder( - borderRadius: _borderRadius, - borderSide: BorderSide( - color: Theme.of(context).primaryColor, - width: 2, - ), - ), - filled: true, - - fillColor: Theme.of(context).cardColor, - ), - keyboardType: keyboardType, - inputFormatters: inputFormatters, - obscureText: obscureText, - validator: validator, - ); - } - - // Gender selector widget - Widget _buildGenderSelector() { - return Container( - decoration: BoxDecoration( - color: Theme.of(context).cardColor, - borderRadius: _borderRadius, - boxShadow: _boxShadow, - ), - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Gender', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Theme.of(context).textTheme.bodyMedium!.color, ), ), - Row( - children: [ - Text('Male', style: TextStyle(color: Colors.grey[700])), - const SizedBox(width: 8), - Obx( - () => Switch( - value: _registerViewModel.selectedGender == 2, - onChanged: (value) { - _registerViewModel.setGender(value ? 2 : 1); - }, - activeColor: Theme.of(context).primaryColor, - inactiveThumbColor: Colors.grey, - ), - ), - const SizedBox(width: 8), - Text('Female', style: TextStyle(color: Colors.grey[700])), - ], - ), - ], + ), ), ); } - // Mobile number row with area code dropdown - Widget _buildMobileNumberRow() { + Widget _buildSectionTitle(String title) { + return Padding( + padding: const EdgeInsets.only(left: 4), + child: Text( + title, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + color: Colors.white, + ), + ), + ); + } + + Widget _buildInputField({ + required TextEditingController controller, + required FocusNode focusNode, + required String label, + TextInputType? keyboardType, + IconData? suffixIcon, + String? Function(String?)? validator, + BorderRadius? borderRadius, // Added parameter for custom border radius + }) { + return TextFormField( + controller: controller, + focusNode: focusNode, + keyboardType: keyboardType, + validator: validator, + style: const TextStyle(color: Colors.white, fontSize: 16), + decoration: InputDecoration( + labelText: label, + labelStyle: const TextStyle(color: Colors.white70, fontSize: 16), + suffixIcon: suffixIcon != null + ? Icon(suffixIcon, color: Colors.white70) + : null, + border: OutlineInputBorder( + borderRadius: borderRadius ?? BorderRadius.circular(12), + borderSide: const BorderSide(color: Colors.white24), + ), + enabledBorder: OutlineInputBorder( + borderRadius: borderRadius ?? BorderRadius.circular(12), + borderSide: const BorderSide(color: Colors.white24), + ), + focusedBorder: OutlineInputBorder( + borderRadius: borderRadius ?? BorderRadius.circular(12), + borderSide: const BorderSide(color: Colors.blue, width: 2), + ), + errorBorder: OutlineInputBorder( + borderRadius: borderRadius ?? BorderRadius.circular(12), + borderSide: const BorderSide(color: Colors.red), + ), + filled: true, + fillColor: Colors.white.withOpacity(0.05), + contentPadding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 16, + ), + ), + ); + } + + Widget _buildDateOfBirthField() { + return GestureDetector( + onTap: () => _selectDate(context), + child: AbsorbPointer( + child: TextFormField( + controller: _dateOfBirthController, + focusNode: _dateOfBirthFocusNode, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please select date of birth'; + } + return null; + }, + style: const TextStyle(color: Colors.white, fontSize: 16), + decoration: InputDecoration( + labelText: 'Date of birth', + labelStyle: const TextStyle(color: Colors.white70, fontSize: 16), + suffixIcon: const Icon( + Icons.keyboard_arrow_down, + color: Colors.white70, + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide(color: Colors.white24), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide(color: Colors.white24), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide(color: Colors.blue, width: 2), + ), + filled: true, + fillColor: Colors.white.withOpacity(0.05), + contentPadding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 16, + ), + ), + ), + ), + ); + } + + Widget _buildPasswordField() { + return TextFormField( + controller: _passwordController, + focusNode: _passwordFocusNode, + obscureText: !_showPassword, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter password'; + } + if (value.length < 8) { + return 'Password must be at least 8 characters'; + } + return null; + }, + style: const TextStyle(color: Colors.white, fontSize: 16), + decoration: InputDecoration( + labelText: 'Password', + labelStyle: const TextStyle(color: Colors.white70, fontSize: 16), + contentPadding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 16, + ), + suffixIcon: TextButton( + onPressed: () { + setState(() { + _showPassword = !_showPassword; + }); + }, + child: Text( + _showPassword ? 'Hide' : 'Show', + style: const TextStyle(color: Colors.white), + ), + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide(color: Colors.white24), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide(color: Colors.white24), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide(color: Colors.blue, width: 2), + ), + filled: true, + fillColor: Colors.white.withOpacity(0.05), + ), + ); + } + + Widget _buildTermsAndConditions() { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - // Compact Area Dropdown (30% width) Expanded( - flex: 1, - child: Obx(() { - // Store current values to prevent rebuilding - final areas = _areaViewModel.areas; - final isLoading = _areaViewModel.isLoading; - final selectedAreaId = _registerViewModel.selectedAreaId; - - return DropdownButtonFormField( - dropdownColor: Theme.of(context).cardColor, - key: const ValueKey('area_dropdown'), - value: selectedAreaId, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.flag_rounded), - border: OutlineInputBorder( - borderRadius: _borderRadius, - borderSide: const BorderSide(color: Colors.grey), - ), - focusedBorder: OutlineInputBorder( - borderRadius: _borderRadius, - borderSide: BorderSide( - color: Theme.of(context).primaryColor, - width: 2, - ), - ), - filled: true, - fillColor: Theme.of(context).cardColor, - alignLabelWithHint: true, + child: RichText( + text: const TextSpan( + style: TextStyle( + fontSize: 14, + color: Colors.white70, + height: 1.4, ), - items: areas.map((area) { - return DropdownMenuItem( - value: area.id, - child: Text( - area.phoneCode, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).textTheme.bodyMedium!.color, - ), + children: [ + TextSpan( + text: + 'I confirm that I am at least 18 years of age, and accept the ', + ), + TextSpan( + text: 'General Terms & Conditions', + style: TextStyle( + color: Colors.blue, + fontWeight: FontWeight.w500, ), - ); - }).toList(), - validator: (value) { - if (value == null) { - return 'Select code'; - } - return null; - }, - onChanged: (value) { - if (value != null) { - _registerViewModel.setSelectedAreaId(value); - } - }, - isExpanded: true, - menuMaxHeight: 250, - hint: isLoading - ? const Center( - child: SizedBox( - height: 20, - width: 20, - child: CircularProgressIndicator(strokeWidth: 2), - ), - ) - : const Text('Code', style: TextStyle(fontSize: 14)), - icon: Icon(Icons.arrow_drop_down, color: Colors.grey), - ); - }), - ), - const SizedBox(width: 10), - - // Mobile Number Field (70% width) - Expanded( - flex: 2, - child: _buildTextFormField( - controller: _mobileController, - focusNode: _mobileFocusNode, - labelText: 'Phone Number', - prefixIcon: Icons.phone_rounded, - keyboardType: TextInputType.phone, - validator: (value) { - if (value == null || value.isEmpty) { - return 'Enter phone number'; - } - if (value.length < 8) { - return 'At least 8 digits'; - } - return null; - }, + ), + ], + ), ), ), ], ); } - // Register button widget - Widget _buildRegisterButton() { + Widget _buildAgreeButton() { return Obx(() { final isLoading = _registerViewModel.isLoading; return SizedBox( width: double.infinity, + height: 56, child: ElevatedButton( - onPressed: isLoading ? null : _submitForm, + onPressed: (isLoading) ? null : _submitForm, style: ElevatedButton.styleFrom( - backgroundColor: Theme.of(context).primaryColor, - foregroundColor: Colors.white, - padding: const EdgeInsets.symmetric(vertical: 16), - shape: RoundedRectangleBorder(borderRadius: _borderRadius), - elevation: 4, - textStyle: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, + backgroundColor: Colors.blue, + foregroundColor: Colors.blue, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), ), + elevation: 0, ), child: isLoading ? const SizedBox( @@ -390,43 +566,110 @@ class _RegisterScreenState extends State { valueColor: AlwaysStoppedAnimation(Colors.white), ), ) - : const Text('Create Account'), + : const Text( + 'Agree and continue', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: Colors.white, + ), + ), ), ); }); } - // Error message widget - Widget _buildErrorMessage() { - return Obx(() { - final errorMessage = _registerViewModel.errorMessage; + Widget _buildSocialButton({ + required icon, + required String text, + required Color backgroundColor, + required Color textColor, + Color? borderColor, + required VoidCallback onTap, + }) { + return SizedBox( + width: double.infinity, + height: 48, + child: ElevatedButton( + onPressed: onTap, + style: ElevatedButton.styleFrom( + backgroundColor: backgroundColor, + foregroundColor: textColor, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + side: borderColor != null + ? BorderSide(color: borderColor) + : BorderSide.none, + ), + elevation: 0, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + SvgIcon(icon, height: SizeUtils.fontSize(28)), + Spacer(), + Text( + text, - return errorMessage.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(top: 12), - child: Text( - errorMessage, - style: const TextStyle( - color: Colors.redAccent, - fontSize: 14, - fontWeight: FontWeight.w500, - ), - textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: textColor, ), - ) - : const SizedBox.shrink(); - }); + ), + Spacer(), + ], + ), + ), + ); + } + + Future _selectDate(BuildContext context) async { + final DateTime? picked = await showDatePicker( + context: context, + initialDate: DateTime.now().subtract( + const Duration(days: 6570), + ), // 18 years ago + firstDate: DateTime.now().subtract( + const Duration(days: 36500), + ), // 100 years ago + lastDate: DateTime.now().subtract( + const Duration(days: 6570), + ), // 18 years ago + builder: (context, child) { + return Theme( + data: Theme.of(context).copyWith( + colorScheme: const ColorScheme.dark( + primary: Colors.blue, + onPrimary: Colors.white, + surface: Color(0xFF1E1E1E), + onSurface: Colors.white, + ), + ), + child: child!, + ); + }, + ); + if (picked != null) { + setState(() { + _selectedDate = picked; + _dateOfBirthController.text = + "${picked.day}/${picked.month}/${picked.year}"; + }); + } } // Submit registration form void _submitForm() { - if (_formKey.currentState!.validate()) { + if (_formKey.currentState!.validate() && _acceptTerms) { _registerViewModel .registerUser( - name: _nameController.text.trim(), - gender: _registerViewModel.selectedGender, - age: int.parse(_ageController.text.trim()), - mobile: _mobileController.text.trim(), + name: _usernameController.text.trim(), + gender: 1, // Default gender + age: _selectedDate != null + ? DateTime.now().year - _selectedDate!.year + : 18, + mobile: _telephoneController.text.trim(), area: _registerViewModel.selectedAreaId ?? 0, password: _passwordController.text.trim(), ) diff --git a/lib/app/widgets/slider_test.dart b/lib/app/widgets/slider_test.dart new file mode 100644 index 0000000..fc18f27 --- /dev/null +++ b/lib/app/widgets/slider_test.dart @@ -0,0 +1,708 @@ +import 'dart:async'; +import 'dart:math'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import '../constants/size_config.dart'; + +class OnBoardingSlider extends StatefulWidget { + const OnBoardingSlider({Key? key}) : super(key: key); + + @override + State createState() => _OnBoardingSliderState(); +} + +class _OnBoardingSliderState extends State { + final PageController _pageController = PageController(); + int _currentPage = 0; + + @override + void initState() { + super.initState(); + // Initialize SizeConfig + WidgetsBinding.instance.addPostFrameCallback((_) { + SizeConfig().init(context); + }); + } + + var imageList = [ + 'assets/icons/s1.png', + 'assets/icons/s2.png', + 'assets/icons/s3.png', + 'assets/icons/s4.png', + 'assets/icons/s5.png', + ]; + + int currentIndex = 0; + + Widget buildDot(int index) { + return Container( + margin: EdgeInsets.all(SizeConfig.getProportionateScreenWidth(5)), + width: SizeConfig.getProportionateScreenWidth(10), + height: SizeConfig.getProportionateScreenHeight(10), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: currentIndex == index ? Colors.white : Colors.grey, + ), + ); + } + + Widget buildGallery3D() { + return Gallery3D( + controller: Gallery3DController( + itemCount: imageList.length, + ellipseHeight: 0, + autoLoop: true, + minScale: 0.4, + delayTime: 2000, + scrollTime: 1000, + ), + width: MediaQuery.of(context).size.width, + height: SizeConfig.getProportionateScreenHeight(300), + isClip: true, + onItemChanged: (index) { + setState(() { + currentIndex = index; + _currentPage = index; + }); + }, + itemConfig: GalleryItemConfig( + width: SizeConfig.getProportionateScreenWidth(180), + height: SizeConfig.getProportionateScreenHeight(850), + radius: SizeConfig.getProportionateScreenWidth(10), + isShowTransformMask: false, + ), + onClickItem: (index) { + if (kDebugMode) print("currentIndex:$index"); + }, + itemBuilder: (context, index) { + return Image.asset(imageList[index], fit: BoxFit.fill); + }, + ); + } + + @override + Widget build(BuildContext context) { + var screenHeight = MediaQuery.of(context).size.height; + + return Column( + children: [ + Container( + height: screenHeight / 4, + child: PageView.builder( + controller: _pageController, + itemCount: imageList.length, + itemBuilder: ((context, index) { + return buildGallery3D(); + }), + onPageChanged: (index) { + setState(() { + _currentPage = index; + }); + }, + ), + ), + VerticalSpacing(16), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: List.generate(imageList.length, (index) => buildDot(index)), + ), + ], + ); + } +} + +class Gallery3D extends StatefulWidget { + final double? height; + final double width; + final IndexedWidgetBuilder itemBuilder; + final ValueChanged? onItemChanged; + final ValueChanged? onClickItem; + final Gallery3DController controller; + final GalleryItemConfig itemConfig; + final EdgeInsetsGeometry? padding; + final bool isClip; + + Gallery3D({ + Key? key, + this.onClickItem, + this.onItemChanged, + this.isClip = true, + this.height, + this.padding, + required this.itemConfig, + required this.controller, + required this.width, + required this.itemBuilder, + }) : super(key: key); + + @override + _Gallery3DState createState() => _Gallery3DState(); +} + +class _Gallery3DState extends State + with TickerProviderStateMixin, WidgetsBindingObserver, Gallery3DMixin { + List _galleryItemWidgetList = []; + AnimationController? _autoScrollAnimationController; + Timer? _timer; + + late Gallery3DController controller = widget.controller; + + AppLifecycleState appLifecycleState = AppLifecycleState.resumed; + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + appLifecycleState = state; + super.didChangeAppLifecycleState(state); + } + + @override + void initState() { + controller.widgetWidth = widget.width; + controller.vsync = this; + controller.init(widget.itemConfig); + + _updateWidgetIndexOnStack(); + if (controller.autoLoop) { + this._timer = Timer.periodic( + Duration(milliseconds: controller.delayTime), + (timer) { + if (!mounted) return; + if (appLifecycleState != AppLifecycleState.resumed) return; + if (DateTime.now().millisecondsSinceEpoch - _lastTouchMillisecond < + controller.delayTime) + return; + if (_isTouching) return; + animateTo( + controller.getOffsetAngleFormTargetIndex( + getNextIndex(controller.currentIndex), + ), + ); + }, + ); + } + + WidgetsBinding.instance.addObserver(this); + + super.initState(); + } + + @override + void dispose() { + WidgetsBinding.instance.removeObserver(this); + _timer?.cancel(); + _timer = null; + _autoScrollAnimationController?.stop(canceled: true); + super.dispose(); + } + + @override + void animateTo(angle) { + _isTouching = true; + _lastTouchMillisecond = DateTime.now().millisecondsSinceEpoch; + _scrollToAngle(angle); + } + + @override + void jumpTo(angle) { + setState(() { + _updateAllGalleryItemTransformByAngle(angle); + }); + } + + var _isTouching = false; + var _lastTouchMillisecond = 0; + Offset? _panDownLocation; + Offset? _lastUpdateLocation; + + @override + Widget build(BuildContext context) { + return Container( + width: widget.width, + height: widget.height ?? widget.itemConfig.height, + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onHorizontalDragCancel: (() { + _onFingerUp(); + }), + onHorizontalDragDown: (details) { + _isTouching = true; + _panDownLocation = details.localPosition; + _lastUpdateLocation = details.localPosition; + _lastTouchMillisecond = DateTime.now().millisecondsSinceEpoch; + }, + onHorizontalDragEnd: (details) { + _onFingerUp(); + }, + onHorizontalDragStart: (details) {}, + onHorizontalDragUpdate: (details) { + setState(() { + _lastUpdateLocation = details.localPosition; + _lastTouchMillisecond = DateTime.now().millisecondsSinceEpoch; + _updateAllGalleryItemTransformByOffsetDx(details.delta.dx); + }); + }, + child: _buildWidgetList(), + ), + ); + } + + Widget _buildWidgetList() { + if (widget.isClip) { + return ClipRect(child: Stack(children: _galleryItemWidgetList)); + } + return Stack(children: _galleryItemWidgetList); + } + + void _scrollToAngle(double angle) { + _autoScrollAnimationController = AnimationController( + duration: Duration(milliseconds: 100), + vsync: this, + ); + + Animation animation; + + if (angle.ceil().abs() == 0) return; + animation = Tween( + begin: 0.0, + end: angle, + ).animate(_autoScrollAnimationController!); + + double lastValue = 0; + animation.addListener(() { + setState(() { + _updateAllGalleryItemTransformByAngle(animation.value - lastValue); + lastValue = animation.value; + }); + }); + _autoScrollAnimationController?.forward(); + _autoScrollAnimationController?.addListener(() { + if (_autoScrollAnimationController != null && + _autoScrollAnimationController!.isCompleted) { + _isTouching = false; + } + }); + } + + void _onFingerUp() { + if (_lastUpdateLocation == null) { + _isTouching = false; + return; + } + + double angle = controller.getTransformInfo(controller.currentIndex).angle; + double targetAngle = 0; + + var offsetX = _lastUpdateLocation!.dx - _panDownLocation!.dx; + + // Adjust the threshold for considering it a swipe + double swipeThreshold = widget.width * 0.1; + + if (offsetX.abs() > swipeThreshold) { + // Swipe detected + if (offsetX > 0) { + // Swipe to the right, move to the bottom + targetAngle = + controller + .getTransformInfo(getPreIndex(controller.currentIndex)) + .angle + + 180; // Move to the bottom + } else { + // Swipe to the left + targetAngle = angle + 180; // Maintain the current position + } + } else { + // No swipe, move to the bottom from the current position + targetAngle = angle + 180; // Move to the bottom + } + + _scrollToAngle(targetAngle); + } + + void _updateAllGalleryItemTransformByAngle(double angle) { + controller.updateTransformByAngle(angle); + _updateAllGalleryItemTransform(); + } + + void _updateAllGalleryItemTransformByOffsetDx(double offsetDx) { + controller.updateTransformByOffsetDx(offsetDx); + _updateAllGalleryItemTransform(); + } + + void _updateAllGalleryItemTransform() { + for (var i = 0; i < controller.getTransformInfoListSize(); i++) { + var item = controller.getTransformInfo(i); + + if (item.angle > 180 - controller.unitAngle / 2 && + item.angle < 180 + controller.unitAngle / 2) { + if (controller.currentIndex != i) { + controller.currentIndex = i; + widget.onItemChanged?.call(controller.currentIndex); + } + } + _updateWidgetIndexOnStack(); + } + } + + /// Get Pre Index >>> + int getPreIndex(int index) { + var preIndex = index - 1; + if (preIndex < 0) { + preIndex = controller.itemCount - 1; + } + return preIndex; + } + + /// Get Next Index >>> + int getNextIndex(int index) { + var nextIndex = index + 1; + if (nextIndex == controller.itemCount) { + nextIndex = 0; + } + return nextIndex; + } + + List _leftWidgetList = []; + List _rightWidgetList = []; + List _tempList = []; + + /// Update Widget Index >>> + void _updateWidgetIndexOnStack() { + _leftWidgetList.clear(); + _rightWidgetList.clear(); + _tempList.clear(); + + for (var i = 0; i < controller.getTransformInfoListSize(); i++) { + var angle = controller.getTransformInfo(i).angle; + + if (angle >= 180 + controller.unitAngle / 2) { + _leftWidgetList.add(_buildGalleryItem(i)); + } else { + _rightWidgetList.add(_buildGalleryItem(i)); + } + } + + _rightWidgetList.sort( + (widget1, widget2) => + widget1.transformInfo.angle.compareTo(widget2.transformInfo.angle), + ); + + _rightWidgetList.forEach((element) { + if (element.transformInfo.angle < controller.unitAngle / 2) { + element.transformInfo.angle += 360; + _tempList.add(element); + } + }); + + _tempList.forEach((element) { + _rightWidgetList.remove(element); + }); + + _leftWidgetList.sort( + (widget1, widget2) => + widget2.transformInfo.angle.compareTo(widget1.transformInfo.angle), + ); + + _galleryItemWidgetList = [..._leftWidgetList, ..._rightWidgetList]; + } + + /// Build Gallery Item >>>>> + GalleryItem _buildGalleryItem(int index) { + return GalleryItem( + index: index, + ellipseHeight: controller.ellipseHeight, + builder: widget.itemBuilder, + config: widget.itemConfig, + onClick: (index) { + if (widget.onClickItem != null && index == controller.currentIndex) { + widget.onClickItem?.call(index); + } + }, + transformInfo: controller.getTransformInfo(index), + ); + } +} + +class _GalleryItemTransformInfo { + Offset offset; + double scale; + double angle; + int index; + + _GalleryItemTransformInfo({ + required this.index, + this.scale = 1, + this.angle = 0, + this.offset = Offset.zero, + }); +} + +class GalleryItem extends StatelessWidget { + final GalleryItemConfig config; + final double ellipseHeight; + final int index; + final IndexedWidgetBuilder builder; + final ValueChanged? onClick; + final _GalleryItemTransformInfo transformInfo; + + final double minScale; + GalleryItem({ + Key? key, + required this.index, + required this.transformInfo, + required this.config, + required this.builder, + this.minScale = 0.4, + this.onClick, + this.ellipseHeight = 0, + }) : super(key: key); + + Widget _buildItem(BuildContext context) { + return Container( + width: config.width, + height: config.height, + child: builder(context, index), + ); + } + + Widget _buildMaskTransformItem(Widget child) { + if (!config.isShowTransformMask) return child; + return Stack( + children: [ + child, + Container( + width: config.width, + height: config.height, + color: Color.fromARGB( + 100 * (1 - transformInfo.scale) ~/ (1 - minScale), + 0, + 0, + 0, + ), + ), + ], + ); + } + + Widget _buildRadiusItem(Widget child) { + if (config.radius <= 0) return child; + return ClipRRect( + borderRadius: BorderRadius.circular(config.radius), + child: child, + ); + } + + Widget _buildShadowItem(Widget child) { + if (config.shadows.isEmpty) return child; + return Container( + child: child, + decoration: BoxDecoration(boxShadow: config.shadows), + ); + } + + @override + Widget build(BuildContext context) { + return Transform.translate( + offset: transformInfo.offset, + child: Container( + width: config.width, + height: config.height, + child: Transform.scale( + scale: transformInfo.scale, + child: InkWell( + highlightColor: Colors.transparent, + splashColor: Colors.transparent, + onTap: () => onClick?.call(index), + child: _buildShadowItem( + _buildRadiusItem(_buildMaskTransformItem(_buildItem(context))), + ), + ), + ), + ), + ); + } +} + +/// Gallery Item Config >>>>> +class GalleryItemConfig { + final double width; + final double height; + final double radius; + final List shadows; + final bool isShowTransformMask; + + const GalleryItemConfig({ + this.width = 220, + this.height = 600, + this.radius = 0, + this.isShowTransformMask = true, + this.shadows = const [], + }); +} + +class Gallery3DController { + double perimeter = 0; + double unitAngle = 0; + final double minScale; + double widgetWidth = 0; + double ellipseHeight; + int itemCount; + late GalleryItemConfig itemConfig; + int currentIndex = 0; + final int delayTime; + final int scrollTime; + final bool autoLoop; + late Gallery3DMixin vsync; + List<_GalleryItemTransformInfo> _galleryItemTransformInfoList = []; + double baseAngleOffset = 0; + Gallery3DController({ + required this.itemCount, + this.ellipseHeight = 0, + this.autoLoop = true, + this.minScale = 0.4, + this.delayTime = 5000, + this.scrollTime = 1000, + }) : assert(itemCount >= 3, 'ItemCount must be greater than or equal to 3'); + + void init(GalleryItemConfig itemConfig) { + this.itemConfig = itemConfig; + unitAngle = 320 / itemCount; + perimeter = calculatePerimeter(widgetWidth * 0.7, 50); + + _galleryItemTransformInfoList.clear(); + for (var i = 0; i < itemCount; i++) { + var itemAngle = getItemAngle(i); + _galleryItemTransformInfoList.add( + _GalleryItemTransformInfo( + index: i, + angle: itemAngle, + scale: calculateScale(itemAngle), + offset: calculateOffset(itemAngle), + ), + ); + } + } + + _GalleryItemTransformInfo getTransformInfo(int index) { + return _galleryItemTransformInfoList[index]; + } + + int getTransformInfoListSize() { + return _galleryItemTransformInfoList.length; + } + + double getItemAngle(int index) { + double angle = 360 - (index * unitAngle + 180) % 360; + return angle; + } + + void updateTransformByAngle(double offsetAngle) { + baseAngleOffset -= offsetAngle; + for (int index = 0; index < _galleryItemTransformInfoList.length; index++) { + _GalleryItemTransformInfo transformInfo = + _galleryItemTransformInfoList[index]; + + double angle = getItemAngle(index); + double scale = transformInfo.scale; + Offset offset = transformInfo.offset; + + if (baseAngleOffset.abs() > 360) { + baseAngleOffset %= 360; + } + + angle += baseAngleOffset; + angle = angle % 360; + + offset = calculateOffset(angle); + + scale = calculateScale(angle); + + transformInfo + ..angle = angle + ..scale = scale + ..offset = offset; + } + } + + void updateTransformByOffsetDx(double offsetDx) { + double offsetAngle = offsetDx / perimeter / 2 * 360; + updateTransformByAngle(offsetAngle); + } + + /// Calculate Scale >>>> + double calculateScale(double angle) { + angle = angle % 360; + if (angle > 180) { + angle = 360 - angle; + } + + angle += 30; + + var scale = angle / 180.0; + + if (scale > 1) { + scale = 1; + } else if (scale < minScale) { + scale = minScale; + } + + return scale; + } + + /// Calculate Offset >>>> + Offset calculateOffset(double angle) { + double width = widgetWidth * 1; + + double radiusOuterX = width / 2.4; + + double radiusOuterY = ellipseHeight; + + double angleOuter = (4 * pi / 360) * angle; + double x = radiusOuterX * sin(angleOuter); + double y = radiusOuterY > 0 ? radiusOuterY * cos(angleOuter) : 0; + + return Offset(x + (widgetWidth - itemConfig.width) / 2, -y); + } + + /// Calculate Perimeter >>>> + double calculatePerimeter(double width, double height) { + var a = width; + // var a = width * 0.8; + var b = height; + return 2 * pi * b + 4 * (a - b); + } + + /// Get Final Angle >>>> + double getFinalAngle(double angle) { + if (angle >= 360) { + angle -= 360; + } else if (angle < 0) { + angle += 360; + } + return angle; + } + + double getOffsetAngleFormTargetIndex(int index) { + double targetItemAngle = getItemAngle(index) + baseAngleOffset; + + double offsetAngle = targetItemAngle % 180; + if (targetItemAngle < 180 || targetItemAngle > 360) { + offsetAngle = offsetAngle - 180; + } + + return offsetAngle; + } + + void animateTo(int index) { + if (index == currentIndex) return; + vsync.animateTo(getOffsetAngleFormTargetIndex(index)); + } + + void jumpTo(int index) { + if (index == currentIndex) return; + vsync.jumpTo(getOffsetAngleFormTargetIndex(index)); + } +} + +mixin class Gallery3DMixin { + void animateTo(angle) {} + void jumpTo(angle) {} +} diff --git a/lib/main.dart b/lib/main.dart index f5f94f1..a83133e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,8 +1,10 @@ import 'package:caller/app/bindings/controllersBindings.dart'; import 'package:caller/app/bindings/themeController.dart'; import 'package:caller/app/modules/chat/MessageModule/database/database_provider.dart'; +import 'package:caller/app/modules/chat/userModule/authModule/views/chineseLoginScreen.dart'; import 'package:caller/app/modules/chat/userModule/authModule/views/loginScreen.dart'; +import 'package:caller/app/modules/chat/userModule/authModule/views/registerScreen.dart'; import 'package:caller/media-module/providers/uploading_provider.dart'; import 'package:caller/media-module/routes/export.dart'; import 'package:caller/media-module/utils/size_config.dart'; diff --git a/lib/media-module/routes/app_pages.dart b/lib/media-module/routes/app_pages.dart index eca8291..1b7aa98 100644 --- a/lib/media-module/routes/app_pages.dart +++ b/lib/media-module/routes/app_pages.dart @@ -4,6 +4,8 @@ import 'package:caller/media-module/view/profile_screen.dart'; import 'package:caller/media-module/view/favourite_screen.dart'; import 'package:caller/media-module/view/camer_screen.dart'; import 'package:caller/media-module/view/wallet_screen.dart'; +import 'package:caller/media-module/view/qr_profile_screen.dart'; +import 'package:caller/media-module/view/history_screen.dart'; class AppPages { static final routes = { @@ -13,5 +15,7 @@ class AppPages { AppRoutes.favouriteScreen: (context) => const FavouriteScreen(), AppRoutes.cameraScreen: (context) => const CameraScreen(), AppRoutes.walletScreen: (context) => WalletScreen(), + AppRoutes.qrProfileScreen: (context) => const QRProfileScreen(), + AppRoutes.historyScreen: (context) => const HistoryScreen(), }; } diff --git a/lib/media-module/routes/app_routes.dart b/lib/media-module/routes/app_routes.dart index 1e49a59..65b2d4d 100644 --- a/lib/media-module/routes/app_routes.dart +++ b/lib/media-module/routes/app_routes.dart @@ -6,4 +6,6 @@ class AppRoutes { static const String favouriteScreen = "favourite-screen"; static const String cameraScreen = "camera-screen"; static const String walletScreen = "wallet-screen"; + static const String qrProfileScreen = "qr-profile-screen"; + static const String historyScreen = "history-screen"; } diff --git a/lib/media-module/view/history_screen.dart b/lib/media-module/view/history_screen.dart new file mode 100644 index 0000000..3abebfd --- /dev/null +++ b/lib/media-module/view/history_screen.dart @@ -0,0 +1,697 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import '../constant/colors.dart'; +import '../utils/size_config.dart'; +import 'package:caller/translations/controller/language_controller.dart'; + +class HistoryScreen extends StatefulWidget { + const HistoryScreen({Key? key}) : super(key: key); + + @override + State createState() => _HistoryScreenState(); +} + +class _HistoryScreenState extends State + with SingleTickerProviderStateMixin { + late TabController _tabController; + final LanguageController languageController = Get.find(); + bool isEditMode = false; + + @override + void initState() { + super.initState(); + _tabController = TabController(length: 4, vsync: this); + } + + @override + void dispose() { + _tabController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBar( + backgroundColor: Colors.white, + elevation: 0, + leading: IconButton( + icon: Icon(Icons.arrow_back, color: Colors.black), + onPressed: () => Navigator.of(context).pop(), + ), + title: Text( + 'watch_history'.tr, + style: TextStyle( + color: Colors.black, + fontSize: SizeUtils.fontSize(18), + fontWeight: FontWeight.w600, + ), + ), + centerTitle: true, + actions: [ + TextButton( + onPressed: () { + setState(() { + isEditMode = !isEditMode; + }); + }, + child: Text( + 'edit'.tr, + style: TextStyle( + color: Colors.black, + fontSize: SizeUtils.fontSize(16), + ), + ), + ), + ], + ), + body: Column( + children: [ + // Tab Bar + Container( + color: Colors.white, + child: TabBar( + controller: _tabController, + labelColor: Colors.black, + unselectedLabelColor: Colors.grey[400], + labelStyle: TextStyle( + fontSize: SizeUtils.fontSize(16), + fontWeight: FontWeight.w600, + ), + unselectedLabelStyle: TextStyle( + fontSize: SizeUtils.fontSize(16), + fontWeight: FontWeight.w400, + ), + indicatorColor: Colors.black, + indicatorWeight: 2, + tabs: [ + Tab(text: 'user'.tr), + Tab(text: 'video'.tr), + Tab(text: 'film_tv'.tr), + Tab(text: 'live'.tr), + ], + ), + ), + + // Filter Button (only for User tab) + if (_tabController.index == 0) + Container( + width: double.infinity, + padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: Align( + alignment: Alignment.centerLeft, + child: Container( + padding: EdgeInsets.symmetric(horizontal: 12, vertical: 6), + decoration: BoxDecoration( + color: Colors.grey[200], + borderRadius: BorderRadius.circular(16), + ), + child: Text( + 'within_week'.tr, + style: TextStyle( + color: Colors.black, + fontSize: SizeUtils.fontSize(14), + ), + ), + ), + ), + ), + + // Tab Content + Expanded( + child: TabBarView( + controller: _tabController, + children: [ + _buildUserTab(), + _buildVideoTab(), + _buildFilmTVTab(), + _buildLiveTab(), + ], + ), + ), + ], + ), + ); + } + + Widget _buildUserTab() { + return SingleChildScrollView( + padding: EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'my_visit_record'.tr, + style: TextStyle( + color: Colors.grey[600], + fontSize: SizeUtils.fontSize(14), + ), + ), + SizedBox(height: 16), + + // Today Section + _buildDateSection('today'.tr, [ + _buildUserItem( + '@-大富大贵', + 'assets/images/wechat/aau.png', + isVerified: false, + buttonText: 'mutual_follow'.tr, + buttonColor: Colors.grey[300]!, + textColor: Colors.black, + ), + _buildUserItem( + '金堂家兴结石病医院...', + 'assets/images/wechat/aay.png', + isVerified: true, + buttonText: 'follow'.tr, + buttonColor: Colors.red, + textColor: Colors.white, + hasUnseenWorks: true, + unseenWorksCount: 9, + ), + ]), + + SizedBox(height: 24), + + // July 30th Section + _buildDateSection('07月30日', [ + _buildUserItem( + '庄小龙', + 'assets/images/wechat/ac9.9.png', + isVerified: true, + buttonText: 'follow'.tr, + buttonColor: Colors.red, + textColor: Colors.white, + hasUnseenWorks: true, + unseenWorksCount: 2, + ), + _buildUserItem( + '一尘道人', + 'assets/images/wechat/aau.png', + isVerified: false, + buttonText: 'return_follow'.tr, + buttonColor: Colors.red, + textColor: Colors.white, + ), + _buildUserItem( + '加点妍01', + 'assets/images/wechat/aay.png', + isVerified: false, + buttonText: 'follow'.tr, + buttonColor: Colors.red, + textColor: Colors.white, + ), + ]), + + SizedBox(height: 24), + + // July 28th Section + _buildDateSection('07月28日', [ + _buildUserItem( + '猪小七', + 'assets/images/wechat/ac9.9.png', + isVerified: false, + buttonText: 'followed'.tr, + buttonColor: Colors.grey[300]!, + textColor: Colors.black, + ), + ]), + ], + ), + ); + } + + Widget _buildVideoTab() { + return _buildEmptyState(); + } + + Widget _buildFilmTVTab() { + return _buildEmptyState(); + } + + Widget _buildLiveTab() { + return SingleChildScrollView( + padding: EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Recently Watched Section + Text( + 'recently_watched'.tr, + style: TextStyle( + color: Colors.black, + fontSize: SizeUtils.fontSize(16), + fontWeight: FontWeight.w600, + ), + ), + SizedBox(height: 12), + Text( + 'recently_watched_not_live'.tr, + style: TextStyle( + color: Colors.grey[600], + fontSize: SizeUtils.fontSize(14), + ), + ), + SizedBox(height: 8), + GestureDetector( + onTap: () { + // Navigate to live channel + }, + child: Text( + 'go_to_live_channel'.tr, + style: TextStyle( + color: Colors.grey[600], + fontSize: SizeUtils.fontSize(14), + ), + ), + ), + + SizedBox(height: 32), + + // Watched Earlier Section + Text( + 'watched_earlier'.tr, + style: TextStyle( + color: Colors.black, + fontSize: SizeUtils.fontSize(16), + fontWeight: FontWeight.w600, + ), + ), + SizedBox(height: 16), + + _buildLiveItem( + '玲洁学姐', + 'assets/images/wechat/aau.png', + 'end_time'.tr + ': 00:33', + 'follow'.tr, + ), + _buildLiveItem( + '茂名茂南啊泽佛州', + 'assets/images/wechat/aay.png', + '佛苗专场', + 'follow'.tr, + isLive: true, + ), + _buildLiveItem( + '流浪猫与单身狗', + 'assets/images/wechat/ac9.9.png', + 'end_time'.tr + ': 01:15', + 'follow'.tr, + ), + _buildLiveItem( + '功夫肥猫', + 'assets/images/wechat/aau.png', + 'end_time'.tr + ': 14:02', + 'follow'.tr, + ), + _buildLiveItem( + '江小帆帆 ✨', + 'assets/images/wechat/aay.png', + 'end_time'.tr + ': 7月29日02:12', + 'followed'.tr, + buttonColor: Colors.grey[300]!, + textColor: Colors.black, + ), + + SizedBox(height: 24), + Center( + child: Text( + 'no_more'.tr, + style: TextStyle( + color: Colors.grey[500], + fontSize: SizeUtils.fontSize(14), + ), + ), + ), + ], + ), + ); + } + + Widget _buildEmptyState() { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // Empty state illustration + Container( + width: 120, + height: 120, + child: Stack( + children: [ + // Background rectangles + Positioned( + top: 20, + left: 20, + child: Container( + width: 60, + height: 40, + decoration: BoxDecoration( + color: Colors.grey[300], + borderRadius: BorderRadius.circular(8), + ), + ), + ), + Positioned( + top: 40, + right: 20, + child: Container( + width: 50, + height: 35, + decoration: BoxDecoration( + color: Colors.grey[300], + borderRadius: BorderRadius.circular(8), + ), + ), + ), + // Sleeping person + Positioned( + bottom: 0, + left: 30, + child: Container( + width: 60, + height: 80, + child: CustomPaint( + painter: SleepingPersonPainter(), + ), + ), + ), + ], + ), + ), + SizedBox(height: 24), + Text( + 'no_watch_history'.tr, + style: TextStyle( + color: Colors.black, + fontSize: SizeUtils.fontSize(16), + fontWeight: FontWeight.w500, + ), + textAlign: TextAlign.center, + ), + SizedBox(height: 8), + Text( + 'go_to_screening_room'.tr, + style: TextStyle( + color: Colors.grey[600], + fontSize: SizeUtils.fontSize(14), + ), + textAlign: TextAlign.center, + ), + SizedBox(height: 32), + Container( + padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12), + decoration: BoxDecoration( + border: Border.all(color: Colors.grey[300]!), + borderRadius: BorderRadius.circular(20), + ), + child: Text( + 'go_to_screening_room_btn'.tr, + style: TextStyle( + color: Colors.black, + fontSize: SizeUtils.fontSize(14), + ), + ), + ), + ], + ), + ); + } + + Widget _buildDateSection(String date, List items) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + date, + style: TextStyle( + color: Colors.grey[600], + fontSize: SizeUtils.fontSize(14), + fontWeight: FontWeight.w500, + ), + ), + SizedBox(height: 12), + ...items, + ], + ); + } + + Widget _buildUserItem( + String name, + String avatarPath, + { + bool isVerified = false, + required String buttonText, + required Color buttonColor, + required Color textColor, + bool hasUnseenWorks = false, + int unseenWorksCount = 0, + } + ) { + return Container( + margin: EdgeInsets.only(bottom: 16), + child: Row( + children: [ + // Avatar + Container( + width: 50, + height: 50, + decoration: BoxDecoration( + shape: BoxShape.circle, + image: DecorationImage( + image: AssetImage(avatarPath), + fit: BoxFit.cover, + ), + ), + ), + SizedBox(width: 12), + + // User info + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + name, + style: TextStyle( + color: Colors.black, + fontSize: SizeUtils.fontSize(16), + fontWeight: FontWeight.w500, + ), + ), + if (isVerified) ...[ + SizedBox(width: 4), + Icon( + Icons.verified, + color: Colors.blue, + size: 16, + ), + ], + ], + ), + if (hasUnseenWorks) ...[ + SizedBox(height: 4), + Container( + padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4), + decoration: BoxDecoration( + color: Colors.grey[200], + borderRadius: BorderRadius.circular(12), + ), + child: Text( + '$unseenWorksCount${'works_not_seen'.tr}', + style: TextStyle( + color: Colors.grey[700], + fontSize: SizeUtils.fontSize(12), + ), + ), + ), + ], + ], + ), + ), + + // Action button + Container( + padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8), + decoration: BoxDecoration( + color: buttonColor, + borderRadius: BorderRadius.circular(16), + ), + child: Text( + buttonText, + style: TextStyle( + color: textColor, + fontSize: SizeUtils.fontSize(14), + fontWeight: FontWeight.w500, + ), + ), + ), + ], + ), + ); + } + + Widget _buildLiveItem( + String name, + String avatarPath, + String subtitle, + String buttonText, { + bool isLive = false, + Color? buttonColor, + Color? textColor, + }) { + return Container( + margin: EdgeInsets.only(bottom: 16), + child: Row( + children: [ + // Avatar with live indicator + Stack( + children: [ + Container( + width: 50, + height: 50, + decoration: BoxDecoration( + shape: BoxShape.circle, + image: DecorationImage( + image: AssetImage(avatarPath), + fit: BoxFit.cover, + ), + ), + ), + if (isLive) + Positioned( + top: 0, + left: 0, + child: Container( + padding: EdgeInsets.symmetric(horizontal: 6, vertical: 2), + decoration: BoxDecoration( + color: Colors.pink, + borderRadius: BorderRadius.circular(8), + ), + child: Text( + '直播', + style: TextStyle( + color: Colors.white, + fontSize: SizeUtils.fontSize(10), + fontWeight: FontWeight.w500, + ), + ), + ), + ), + ], + ), + SizedBox(width: 12), + + // User info + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + name, + style: TextStyle( + color: Colors.black, + fontSize: SizeUtils.fontSize(16), + fontWeight: FontWeight.w500, + ), + ), + SizedBox(height: 2), + Text( + subtitle, + style: TextStyle( + color: Colors.grey[600], + fontSize: SizeUtils.fontSize(14), + ), + ), + ], + ), + ), + + // Action button + Container( + padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8), + decoration: BoxDecoration( + color: buttonColor ?? Colors.red, + borderRadius: BorderRadius.circular(16), + ), + child: Text( + buttonText, + style: TextStyle( + color: textColor ?? Colors.white, + fontSize: SizeUtils.fontSize(14), + fontWeight: FontWeight.w500, + ), + ), + ), + ], + ), + ); + } +} + +// Custom painter for the sleeping person illustration +class SleepingPersonPainter extends CustomPainter { + @override + void paint(Canvas canvas, Size size) { + final paint = Paint() + ..color = Colors.blue[700]! + ..style = PaintingStyle.fill; + + // Head + canvas.drawCircle( + Offset(size.width * 0.5, size.height * 0.2), + size.width * 0.15, + paint, + ); + + // Body + final bodyPath = Path(); + bodyPath.moveTo(size.width * 0.35, size.height * 0.35); + bodyPath.lineTo(size.width * 0.65, size.height * 0.35); + bodyPath.lineTo(size.width * 0.7, size.height * 0.8); + bodyPath.lineTo(size.width * 0.3, size.height * 0.8); + bodyPath.close(); + canvas.drawPath(bodyPath, paint); + + // Arms + canvas.drawRect( + Rect.fromLTWH(size.width * 0.25, size.height * 0.4, size.width * 0.1, size.height * 0.2), + paint, + ); + canvas.drawRect( + Rect.fromLTWH(size.width * 0.65, size.height * 0.4, size.width * 0.1, size.height * 0.2), + paint, + ); + + // Legs + canvas.drawRect( + Rect.fromLTWH(size.width * 0.35, size.height * 0.8, size.width * 0.08, size.height * 0.2), + paint, + ); + canvas.drawRect( + Rect.fromLTWH(size.width * 0.57, size.height * 0.8, size.width * 0.08, size.height * 0.2), + paint, + ); + + // Zz text + final textPainter = TextPainter( + text: TextSpan( + text: 'Zz', + style: TextStyle( + color: Colors.grey[600], + fontSize: size.width * 0.2, + fontWeight: FontWeight.bold, + ), + ), + textDirection: TextDirection.ltr, + ); + textPainter.layout(); + textPainter.paint(canvas, Offset(size.width * 0.7, size.height * 0.1)); + } + + @override + bool shouldRepaint(covariant CustomPainter oldDelegate) => false; +} \ No newline at end of file diff --git a/lib/media-module/view/offline_mode_screen.dart b/lib/media-module/view/offline_mode_screen.dart new file mode 100644 index 0000000..01de811 --- /dev/null +++ b/lib/media-module/view/offline_mode_screen.dart @@ -0,0 +1,204 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import '../utils/size_config.dart'; +import 'offline_settings_screen.dart'; +import 'package:caller/translations/controller/language_controller.dart'; + +class OfflineModeScreen extends StatelessWidget { + final LanguageController languageController = Get.put(LanguageController()); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Color(0xFF1e3a5f), + body: SafeArea( + child: Column( + children: [ + // Header + Container( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getProportionateScreenWidth(20), + vertical: SizeUtils.getProportionateScreenHeight(15), + ), + child: Row( + children: [ + InkWell( + onTap: () => Navigator.of(context).pop(), + child: Icon( + Icons.arrow_back, + color: Colors.white, + size: SizeUtils.getProportionateScreenWidth(24), + ), + ), + Expanded( + child: Center( + child: Text( + 'offline_mode'.tr, + style: TextStyle( + color: Colors.white, + fontSize: SizeUtils.fontSize(18), + fontWeight: FontWeight.w600, + ), + ), + ), + ), + SizedBox(width: SizeUtils.getProportionateScreenWidth(24)), + ], + ), + ), + + // Main content + Expanded( + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // Box icon with butterfly + Stack( + alignment: Alignment.center, + children: [ + // Box icon + Container( + width: SizeUtils.getProportionateScreenWidth(80), + height: SizeUtils.getProportionateScreenHeight(80), + decoration: BoxDecoration( + color: Color(0xFF4A90E2), + borderRadius: BorderRadius.circular(12), + ), + child: Icon( + Icons.inbox_outlined, + color: Colors.white, + size: SizeUtils.getProportionateScreenWidth(40), + ), + ), + // Butterfly with dotted line + Positioned( + top: -20, + child: Column( + children: [ + Icon( + Icons.flutter_dash, + color: Colors.white, + size: SizeUtils.getProportionateScreenWidth(20), + ), + Container( + width: 2, + height: 15, + decoration: BoxDecoration( + border: Border( + left: BorderSide( + color: Colors.white, + width: 1, + style: BorderStyle.solid, + ), + ), + ), + child: CustomPaint( + painter: DottedLinePainter(), + ), + ), + ], + ), + ), + ], + ), + + SizedBox(height: SizeUtils.getProportionateScreenHeight(30)), + + // Text content + Text( + 'no_content_yet'.tr, + style: TextStyle( + color: Colors.white, + fontSize: SizeUtils.fontSize(16), + fontWeight: FontWeight.w500, + ), + ), + SizedBox(height: SizeUtils.getProportionateScreenHeight(8)), + Text( + 'cached_content_will_show_here'.tr, + style: TextStyle( + color: Colors.white.withOpacity(0.7), + fontSize: SizeUtils.fontSize(14), + ), + ), + ], + ), + ), + ), + + // Bottom section + Container( + padding: EdgeInsets.all(SizeUtils.getProportionateScreenWidth(20)), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'no_cached_content'.tr, + style: TextStyle( + color: Colors.white.withOpacity(0.7), + fontSize: SizeUtils.fontSize(14), + ), + ), + ElevatedButton( + onPressed: () { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => OfflineSettingsScreen(), + ), + ); + }, + style: ElevatedButton.styleFrom( + backgroundColor: Color(0xFF4A90E2), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getProportionateScreenWidth(20), + vertical: SizeUtils.getProportionateScreenHeight(10), + ), + ), + child: Text( + 'offline_settings'.tr, + style: TextStyle( + color: Colors.white, + fontSize: SizeUtils.fontSize(14), + fontWeight: FontWeight.w500, + ), + ), + ), + ], + ), + ), + ], + ), + ), + ); + } +} + +class DottedLinePainter extends CustomPainter { + @override + void paint(Canvas canvas, Size size) { + final paint = Paint() + ..color = Colors.white + ..strokeWidth = 1 + ..style = PaintingStyle.stroke; + + const dashWidth = 3; + const dashSpace = 3; + double startY = 0; + + while (startY < size.height) { + canvas.drawLine( + Offset(0, startY), + Offset(0, startY + dashWidth), + paint, + ); + startY += dashWidth + dashSpace; + } + } + + @override + bool shouldRepaint(covariant CustomPainter oldDelegate) => false; +} \ No newline at end of file diff --git a/lib/media-module/view/offline_settings_screen.dart b/lib/media-module/view/offline_settings_screen.dart new file mode 100644 index 0000000..b7d06c8 --- /dev/null +++ b/lib/media-module/view/offline_settings_screen.dart @@ -0,0 +1,481 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import '../utils/size_config.dart'; +import 'package:caller/translations/controller/language_controller.dart'; + +class OfflineSettingsScreen extends StatefulWidget { + @override + _OfflineSettingsScreenState createState() => _OfflineSettingsScreenState(); +} + +class _OfflineSettingsScreenState extends State { + final LanguageController languageController = Get.put(LanguageController()); + int selectedVideoCount = 100; + bool autoReplaceEnabled = true; + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Color(0xFF1e3a5f), + body: SafeArea( + child: GestureDetector( + onTap: () { + // Close panel when tapping on the blue background + Navigator.of(context).pop(); + }, + child: Column( + children: [ + // Header + Container( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getProportionateScreenWidth(20), + vertical: SizeUtils.getProportionateScreenHeight(15), + ), + child: Row( + children: [ + InkWell( + onTap: () => Navigator.of(context).pop(), + child: Icon( + Icons.arrow_back, + color: Colors.white, + size: SizeUtils.getProportionateScreenWidth(24), + ), + ), + Expanded( + child: Center( + child: Text( + 'offline_mode'.tr, + style: TextStyle( + color: Colors.white, + fontSize: SizeUtils.fontSize(18), + fontWeight: FontWeight.w600, + ), + ), + ), + ), + SizedBox(width: SizeUtils.getProportionateScreenWidth(24)), + ], + ), + ), + + // Decorative graphic + Container( + height: SizeUtils.getProportionateScreenHeight(120), + child: Center( + child: Stack( + alignment: Alignment.center, + children: [ + // Box icon + Container( + width: SizeUtils.getProportionateScreenWidth(80), + height: SizeUtils.getProportionateScreenHeight(80), + decoration: BoxDecoration( + color: Color(0xFF4A90E2), + borderRadius: BorderRadius.circular(12), + ), + child: Icon( + Icons.inbox_outlined, + color: Colors.white, + size: SizeUtils.getProportionateScreenWidth(40), + ), + ), + // Butterfly with dotted line + Positioned( + top: -20, + child: Column( + children: [ + Icon( + Icons.flutter_dash, + color: Colors.white, + size: SizeUtils.getProportionateScreenWidth(20), + ), + Container( + width: 2, + height: 15, + child: CustomPaint(painter: DottedLinePainter()), + ), + ], + ), + ), + ], + ), + ), + ), + + // Settings panel + Expanded( + child: GestureDetector( + onTap: () { + // Prevent closing when tapping inside the panel + }, + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(20), + topRight: Radius.circular(20), + ), + ), + child: Column( + children: [ + // Handle + Container( + margin: EdgeInsets.only( + top: SizeUtils.getProportionateScreenHeight(10), + ), + width: SizeUtils.getProportionateScreenWidth(40), + height: 4, + decoration: BoxDecoration( + color: Colors.grey[300], + borderRadius: BorderRadius.circular(2), + ), + ), + + // Title + Padding( + padding: EdgeInsets.all( + SizeUtils.getProportionateScreenWidth(20), + ), + child: Text( + 'offline_mode_settings'.tr, + style: TextStyle( + fontSize: SizeUtils.fontSize(18), + fontWeight: FontWeight.w600, + color: Colors.black87, + ), + ), + ), + + // Video quantity options + Padding( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getProportionateScreenWidth( + 20, + ), + ), + child: Column( + children: [ + _buildVideoOption( + 100, + 'videos_100'.tr, + 'estimated_270mb_30min'.tr, + ), + SizedBox( + height: SizeUtils.getProportionateScreenHeight( + 15, + ), + ), + _buildVideoOption( + 150, + 'videos_150'.tr, + 'estimated_320mb_45min'.tr, + ), + SizedBox( + height: SizeUtils.getProportionateScreenHeight( + 15, + ), + ), + _buildVideoOption( + 200, + 'videos_200'.tr, + 'estimated_400mb_60min'.tr, + ), + ], + ), + ), + + SizedBox( + height: SizeUtils.getProportionateScreenHeight(30), + ), + + // Auto-replacement toggle + Padding( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getProportionateScreenWidth( + 20, + ), + ), + child: Row( + children: [ + Expanded( + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Text( + 'auto_replace_wifi'.tr, + style: TextStyle( + fontSize: SizeUtils.fontSize(12), + color: Colors.black87, + ), + maxLines: 3, + overflow: TextOverflow.ellipsis, + ), + ), + SizedBox( + width: + SizeUtils.getProportionateScreenWidth( + 5, + ), + ), + // Icon( + // Icons.help_outline, + // size: SizeUtils.getProportionateScreenWidth( + // 16, + // ), + // color: Colors.grey[600], + // ), + ], + ), + ), + Switch( + value: autoReplaceEnabled, + onChanged: (value) { + setState(() { + autoReplaceEnabled = value; + }); + // Close the settings panel after switching + Navigator.of(context).pop(); + }, + activeColor: Colors.green, + ), + ], + ), + ), + + Spacer(), + + // Action buttons + Padding( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getProportionateScreenWidth( + 20, + ), + vertical: SizeUtils.getProportionateScreenHeight( + 20, + ), + ), + child: Row( + children: [ + Expanded( + child: ElevatedButton( + onPressed: () { + // Clear all functionality + _showClearAllDialog(); + }, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.grey[300], + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + padding: EdgeInsets.symmetric( + vertical: + SizeUtils.getProportionateScreenHeight( + 12, + ), + ), + ), + child: Text( + 'clear_all'.tr, + style: TextStyle( + color: Colors.black87, + fontSize: SizeUtils.fontSize(14), + fontWeight: FontWeight.w500, + ), + ), + ), + ), + SizedBox( + width: SizeUtils.getProportionateScreenWidth( + 15, + ), + ), + Expanded( + child: ElevatedButton( + onPressed: () { + // Start caching functionality + _startCaching(); + }, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.red, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + padding: EdgeInsets.symmetric( + vertical: + SizeUtils.getProportionateScreenHeight( + 12, + ), + ), + ), + child: Text( + 'start_caching'.tr, + style: TextStyle( + color: Colors.white, + fontSize: SizeUtils.fontSize(14), + fontWeight: FontWeight.w500, + ), + ), + ), + ), + ], + ), + ), + + // Storage information + Padding( + padding: EdgeInsets.only( + bottom: SizeUtils.getProportionateScreenHeight(20), + left: SizeUtils.getProportionateScreenWidth(20), + right: SizeUtils.getProportionateScreenWidth(20), + ), + child: Text( + 'used_0mb_available_5gb'.tr, + style: TextStyle( + fontSize: SizeUtils.fontSize(12), + color: Colors.grey[600], + ), + ), + ), + ], + ), + ), + ), + ), + ], + ), + ), + ), + ); + } + + Widget _buildVideoOption(int count, String title, String subtitle) { + bool isSelected = selectedVideoCount == count; + + return InkWell( + onTap: () { + setState(() { + selectedVideoCount = count; + }); + }, + child: Container( + padding: EdgeInsets.all(SizeUtils.getProportionateScreenWidth(15)), + decoration: BoxDecoration( + border: Border.all( + color: isSelected ? Colors.red : Colors.grey[300]!, + width: 1, + ), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: TextStyle( + fontSize: SizeUtils.fontSize(14), + fontWeight: FontWeight.w500, + color: Colors.black87, + ), + ), + SizedBox(height: SizeUtils.getProportionateScreenHeight(4)), + Text( + subtitle, + style: TextStyle( + fontSize: SizeUtils.fontSize(12), + color: Colors.grey[600], + ), + ), + ], + ), + ), + Container( + width: SizeUtils.getProportionateScreenWidth(20), + height: SizeUtils.getProportionateScreenHeight(20), + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: isSelected ? Colors.red : Colors.grey[400]!, + width: 2, + ), + ), + child: isSelected + ? Icon( + Icons.check, + size: SizeUtils.getProportionateScreenWidth(14), + color: Colors.red, + ) + : null, + ), + ], + ), + ), + ); + } + + void _showClearAllDialog() { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: Text('confirm_clear_all'.tr), + content: Text('confirm_clear_message'.tr), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: Text('cancel'.tr), + ), + TextButton( + onPressed: () { + Navigator.of(context).pop(); + // Clear all functionality + ScaffoldMessenger.of( + context, + ).showSnackBar(SnackBar(content: Text('clear_all'.tr))); + }, + child: Text('confirm'.tr), + ), + ], + ); + }, + ); + } + + void _startCaching() { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + '${'caching_started'.tr} ${selectedVideoCount} ${'videos_100'.tr.split(' ')[1]}...', + ), + duration: Duration(seconds: 2), + ), + ); + // Navigate back to offline mode screen + Navigator.of(context).pop(); + } +} + +class DottedLinePainter extends CustomPainter { + @override + void paint(Canvas canvas, Size size) { + final paint = Paint() + ..color = Colors.white + ..strokeWidth = 1 + ..style = PaintingStyle.stroke; + + const dashWidth = 3; + const dashSpace = 3; + double startY = 0; + + while (startY < size.height) { + canvas.drawLine(Offset(0, startY), Offset(0, startY + dashWidth), paint); + startY += dashWidth + dashSpace; + } + } + + @override + bool shouldRepaint(covariant CustomPainter oldDelegate) => false; +} diff --git a/lib/media-module/view/profile_screen.dart b/lib/media-module/view/profile_screen.dart index 89439b5..5c70186 100644 --- a/lib/media-module/view/profile_screen.dart +++ b/lib/media-module/view/profile_screen.dart @@ -1,3 +1,5 @@ +import 'package:caller/media-module/view/qr_profile_screen.dart' + show QRProfileScreen; import 'package:caller/media-module/widget/custom_drawer.dart'; import 'package:flutter/material.dart'; import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; @@ -11,6 +13,7 @@ import '../widget/profile_grid_item.dart'; import '../models/profile_grid_item_model.dart'; import 'package:get/get.dart'; import 'package:caller/translations/controller/language_controller.dart'; +import 'package:caller/media-module/routes/app_routes.dart'; class ProfileScreen extends StatefulWidget { @override @@ -146,6 +149,11 @@ class _ProfileScreenState extends State { onFindFriends: () { // Handle find friends }, + onQRCode: () { + Navigator.of(context).push( + MaterialPageRoute(builder: (context) => QRProfileScreen()), + ); + }, ), SizedBox(height: SizeUtils.height(20)), diff --git a/lib/media-module/view/qr_profile_screen.dart b/lib/media-module/view/qr_profile_screen.dart new file mode 100644 index 0000000..7219e17 --- /dev/null +++ b/lib/media-module/view/qr_profile_screen.dart @@ -0,0 +1,242 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import '../constant/colors.dart'; +import '../utils/size_config.dart'; + +class QRProfileScreen extends StatelessWidget { + const QRProfileScreen({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [Color(0xFF1D304D), Color(0xFF1A1A1A), Color(0xFF1A1A1A)], + stops: [0.0, 0.5, 1.0], + ), + ), + child: SafeArea( + child: Column( + children: [ + // Top Bar with Status + _buildTopBar(context), + + // Main Content + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // QR Code Section + _buildQRCodeSection(), + + SizedBox( + height: SizeUtils.getProportionateScreenHeight(30), + ), + + // Profile Information + _buildProfileInfo(context), + + SizedBox( + height: SizeUtils.getProportionateScreenHeight(50), + ), + + // Action Buttons + _buildActionButtons(context), + ], + ), + ), + ], + ), + ), + ), + ); + } + + Widget _buildTopBar(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // Back Button + IconButton( + onPressed: () { + Navigator.of(context).pop(); + }, + icon: const Icon(Icons.arrow_back, color: Colors.white, size: 24), + ), + + // Share Button + IconButton( + onPressed: () {}, + icon: const Icon(Icons.share, color: Colors.white, size: 24), + ), + ], + ), + ); + } + + Widget _buildQRCodeSection() { + return Image.asset( + "assets/icons/qrr.png", + width: SizeUtils.getProportionateScreenWidth(280), + height: SizeUtils.getProportionateScreenWidth(280), + ); + } + + Widget _buildProfileInfo(BuildContext context) { + return Column( + children: [ + // Username + Text( + '武唐coffee', + style: TextStyle( + color: Colors.white, + fontSize: SizeUtils.fontSize(24), + fontWeight: FontWeight.bold, + ), + ), + + SizedBox(height: SizeUtils.getProportionateScreenHeight(10)), + + // Douyin ID with copy button + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + '抖音号: 359640478', + style: TextStyle( + color: Colors.white, + fontSize: SizeUtils.fontSize(16), + ), + ), + SizedBox(width: SizeUtils.getProportionateScreenWidth(8)), + GestureDetector( + onTap: () { + Clipboard.setData(const ClipboardData(text: '359640478')); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('ID copied to clipboard')), + ); + }, + child: Container( + padding: const EdgeInsets.all(4), + decoration: BoxDecoration( + color: Colors.white.withOpacity(0.2), + borderRadius: BorderRadius.circular(4), + ), + child: const Icon(Icons.copy, color: Colors.white, size: 16), + ), + ), + ], + ), + + SizedBox(height: SizeUtils.getProportionateScreenHeight(15)), + + // Scan instruction + Text( + '抖音扫一扫,立即关注我', + style: TextStyle( + color: Colors.white.withOpacity(0.9), + fontSize: SizeUtils.fontSize(14), + ), + ), + ], + ); + } + + Widget _buildActionButtons(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + _buildActionButton( + icon: Icons.qr_code_scanner, + label: '扫一扫', + onTap: () { + ScaffoldMessenger.of( + context, + ).showSnackBar(const SnackBar(content: Text('Scan QR Code'))); + }, + ), + _buildActionButton( + icon: Icons.person, + label: 'AI 抖音码', + isProfile: true, + onTap: () { + ScaffoldMessenger.of( + context, + ).showSnackBar(const SnackBar(content: Text('AI Douyin Code'))); + }, + ), + _buildActionButton( + icon: Icons.download, + label: '保存', + onTap: () { + ScaffoldMessenger.of( + context, + ).showSnackBar(const SnackBar(content: Text('QR Code Saved'))); + }, + ), + ], + ); + } + + Widget _buildActionButton({ + required IconData icon, + required String label, + required VoidCallback onTap, + bool isProfile = false, + }) { + return GestureDetector( + onTap: onTap, + child: Column( + children: [ + Container( + width: SizeUtils.getProportionateScreenWidth(60), + height: SizeUtils.getProportionateScreenWidth(60), + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + Color(0xFF1D304D), + Color(0xFF1D304D), + Color(0xFF1A1A1A), + ], + stops: [0.0, 0.5, 1.0], + ), + color: const Color(0xFF9370DB), + shape: BoxShape.circle, + ), + child: isProfile + ? Container( + decoration: BoxDecoration( + shape: BoxShape.circle, + image: const DecorationImage( + image: NetworkImage( + 'https://picsum.photos/100/100?random=1', + ), + fit: BoxFit.cover, + ), + ), + ) + : Icon(icon, color: Colors.white, size: 24), + ), + SizedBox(height: SizeUtils.getProportionateScreenHeight(8)), + Text( + label, + style: TextStyle( + color: Colors.white, + fontSize: SizeUtils.fontSize(12), + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ); + } +} + +// Custom painter for QR code pattern diff --git a/lib/media-module/widget/custom_drawer.dart b/lib/media-module/widget/custom_drawer.dart index 226aaea..9df1aa2 100644 --- a/lib/media-module/widget/custom_drawer.dart +++ b/lib/media-module/widget/custom_drawer.dart @@ -1,4 +1,7 @@ import 'package:caller/media-module/constant/images.dart'; +import 'package:caller/media-module/view/history_screen.dart'; +import 'package:caller/media-module/view/live_streaming_preview.dart'; +import 'package:caller/media-module/view/qr_profile_screen.dart'; import 'package:caller/media-module/widget/svgicon.dart'; import 'package:flutter/material.dart'; import '../utils/size_config.dart'; @@ -9,6 +12,7 @@ import 'package:caller/media-module/view/favourite_screen.dart'; import 'package:caller/media-module/view/camer_screen.dart'; import 'package:caller/media-module/view/main_screen.dart'; import 'package:caller/media-module/view/wallet_screen.dart'; +import 'package:caller/media-module/view/offline_mode_screen.dart'; // Simple tab controller class TabController extends GetxController { @@ -54,7 +58,20 @@ class CustomDrawer extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Icon(Icons.center_focus_strong, color: Colors.white), + InkWell( + onTap: () { + Navigator.of(context).pop(); + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => QRProfileScreen(), + ), + ); + }, + child: Icon( + Icons.center_focus_strong, + color: Colors.white, + ), + ), InkWell( onTap: () { Navigator.of(context).pop(); @@ -73,7 +90,9 @@ class CustomDrawer extends StatelessWidget { Container( width: double.infinity, - margin: EdgeInsets.symmetric(horizontal: SizeUtils.getProportionateScreenWidth(6)), + margin: EdgeInsets.symmetric( + horizontal: SizeUtils.getProportionateScreenWidth(6), + ), padding: EdgeInsets.all(15), decoration: BoxDecoration( @@ -81,7 +100,9 @@ class CustomDrawer extends StatelessWidget { color: Colors.white.withOpacity(0.3), width: 1, ), - borderRadius: BorderRadius.circular(SizeUtils.getProportionateScreenWidth(6)), + borderRadius: BorderRadius.circular( + SizeUtils.getProportionateScreenWidth(6), + ), gradient: LinearGradient( begin: Alignment.bottomRight, @@ -108,7 +129,9 @@ class CustomDrawer extends StatelessWidget { ), ), - SizedBox(height: SizeUtils.getProportionateScreenHeight(10)), + SizedBox( + height: SizeUtils.getProportionateScreenHeight(10), + ), // 2-column grid buttons Wrap( @@ -131,15 +154,19 @@ class CustomDrawer extends StatelessWidget { SizedBox(height: SizeUtils.getProportionateScreenHeight(10)), // History item Padding( - padding: EdgeInsets.symmetric(horizontal: SizeUtils.getProportionateScreenWidth(6)), - child: _buildHistoryItem(), + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getProportionateScreenWidth(6), + ), + child: _buildHistoryItem(context), ), SizedBox(height: SizeUtils.getProportionateScreenHeight(10)), // Language Switch item Padding( - padding: EdgeInsets.symmetric(horizontal: SizeUtils.getProportionateScreenWidth(6)), + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getProportionateScreenWidth(6), + ), child: _buildLanguageItem(), ), @@ -160,6 +187,12 @@ class CustomDrawer extends StatelessWidget { // Navigate to wallet screen Navigator.of(context).pop(); // Close drawer Get.to(() => WalletScreen()); + } else if (label == 'shoot'.tr) { + // Navigate back to main screen and show favorites + Navigator.of(context).pop(); // Close drawer + Navigator.of(context).push( + MaterialPageRoute(builder: (context) => LiveStreamingPreview()), + ); } else if (label == 'favorites_media'.tr) { // Navigate back to main screen and show favorites Navigator.of(context).pop(); // Close drawer @@ -176,22 +209,36 @@ class CustomDrawer extends StatelessWidget { TabController.to.changeTab(2); } Get.offAll(() => MainScreen()); + } else if (label == 'saved'.tr) { + // Navigate to offline mode screen + Navigator.of(context).pop(); // Close drawer + Navigator.of( + context, + ).push(MaterialPageRoute(builder: (context) => OfflineModeScreen())); } // Add other navigation handlers as needed }, child: Container( - width: SizeUtils.getProportionateScreenWidth(110), // Half width with spacing + width: SizeUtils.getProportionateScreenWidth( + 110, + ), // Half width with spacing height: SizeUtils.getProportionateScreenHeight(40), padding: EdgeInsets.only(left: 10), decoration: BoxDecoration( border: Border.all(color: Colors.white.withOpacity(0.3), width: 1), - borderRadius: BorderRadius.circular(SizeUtils.getProportionateScreenWidth(6)), + borderRadius: BorderRadius.circular( + SizeUtils.getProportionateScreenWidth(6), + ), color: Colors.transparent, ), child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ - SvgIcon(icon, color: Colors.white, height: SizeUtils.getProportionateScreenWidth(16)), + SvgIcon( + icon, + color: Colors.white, + height: SizeUtils.getProportionateScreenWidth(16), + ), SizedBox(width: SizeUtils.getProportionateScreenWidth(10)), Flexible( child: Text( @@ -211,34 +258,50 @@ class CustomDrawer extends StatelessWidget { } /// History item (with right arrow) - Widget _buildHistoryItem() { - return Container( - height: SizeUtils.getProportionateScreenHeight(45), - decoration: BoxDecoration( - border: Border.all(color: Colors.white.withOpacity(0.3), width: 1), - borderRadius: BorderRadius.circular(SizeUtils.getProportionateScreenWidth(6)), - ), - padding: EdgeInsets.symmetric(horizontal: SizeUtils.getProportionateScreenWidth(15)), - child: Row( - children: [ - Icon(Icons.history, color: Colors.white, size: SizeUtils.getProportionateScreenWidth(18)), - SizedBox(width: SizeUtils.getProportionateScreenWidth(10)), - Expanded( - child: Text( - 'history'.tr, - style: TextStyle( - color: Colors.white, - fontSize: SizeUtils.fontSize(14), - fontWeight: FontWeight.w400, + Widget _buildHistoryItem(BuildContext context) { + return InkWell( + onTap: () { + Navigator.of(context).pop(); // Close drawer + Navigator.of( + context, + ).push(MaterialPageRoute(builder: (context) => HistoryScreen())); + }, + child: Container( + height: SizeUtils.getProportionateScreenHeight(45), + decoration: BoxDecoration( + border: Border.all(color: Colors.white.withOpacity(0.3), width: 1), + borderRadius: BorderRadius.circular( + SizeUtils.getProportionateScreenWidth(6), + ), + ), + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getProportionateScreenWidth(15), + ), + child: Row( + children: [ + Icon( + Icons.history, + color: Colors.white, + size: SizeUtils.getProportionateScreenWidth(18), + ), + SizedBox(width: SizeUtils.getProportionateScreenWidth(10)), + Expanded( + child: Text( + 'history'.tr, + style: TextStyle( + color: Colors.white, + fontSize: SizeUtils.fontSize(14), + fontWeight: FontWeight.w400, + ), ), ), - ), - Icon( - Icons.chevron_right, - color: Colors.white, - size: SizeUtils.getProportionateScreenWidth(20), - ), - ], + Icon( + Icons.chevron_right, + color: Colors.white, + size: SizeUtils.getProportionateScreenWidth(20), + ), + ], + ), ), ); } @@ -249,12 +312,20 @@ class CustomDrawer extends StatelessWidget { height: SizeUtils.getProportionateScreenHeight(45), decoration: BoxDecoration( border: Border.all(color: Colors.white.withOpacity(0.3), width: 1), - borderRadius: BorderRadius.circular(SizeUtils.getProportionateScreenWidth(6)), + borderRadius: BorderRadius.circular( + SizeUtils.getProportionateScreenWidth(6), + ), + ), + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getProportionateScreenWidth(15), ), - padding: EdgeInsets.symmetric(horizontal: SizeUtils.getProportionateScreenWidth(15)), child: Row( children: [ - Icon(Icons.language, color: Colors.white, size: SizeUtils.getProportionateScreenWidth(18)), + Icon( + Icons.language, + color: Colors.white, + size: SizeUtils.getProportionateScreenWidth(18), + ), SizedBox(width: SizeUtils.getProportionateScreenWidth(10)), Expanded( child: Text( diff --git a/lib/media-module/widget/profile_action_buttons.dart b/lib/media-module/widget/profile_action_buttons.dart index 727856d..294180b 100644 --- a/lib/media-module/widget/profile_action_buttons.dart +++ b/lib/media-module/widget/profile_action_buttons.dart @@ -6,6 +6,7 @@ import 'package:get/get.dart'; class ProfileActionButtons extends StatelessWidget { final VoidCallback? onEditProfile; final VoidCallback? onFindFriends; + final VoidCallback? onQRCode; final String? editProfileText; final String? findFriendsText; @@ -13,6 +14,7 @@ class ProfileActionButtons extends StatelessWidget { Key? key, this.onEditProfile, this.onFindFriends, + this.onQRCode, this.editProfileText, this.findFriendsText, }) : super(key: key); @@ -21,46 +23,79 @@ class ProfileActionButtons extends StatelessWidget { Widget build(BuildContext context) { return Padding( padding: EdgeInsets.symmetric(horizontal: SizeUtils.width(16)), - child: Row( + child: Column( children: [ - Expanded( - child: GestureDetector( - onTap: onEditProfile, - child: Container( - padding: EdgeInsets.symmetric(vertical: SizeUtils.height(12)), - decoration: BoxDecoration( - color: Color(0xFF2A2A2A), - borderRadius: BorderRadius.circular(SizeUtils.width(10)), - ), - child: Center( - child: CustomText( - text: 'edit_profile'.tr, - fontSize: SizeUtils.fontSize(14), - fontWeight: FontWeight.w500, - color: Colors.white, + Row( + children: [ + Expanded( + child: GestureDetector( + onTap: onEditProfile, + child: Container( + padding: EdgeInsets.symmetric(vertical: SizeUtils.height(12)), + decoration: BoxDecoration( + color: Color(0xFF2A2A2A), + borderRadius: BorderRadius.circular(SizeUtils.width(10)), + ), + child: Center( + child: CustomText( + text: 'edit_profile'.tr, + fontSize: SizeUtils.fontSize(14), + fontWeight: FontWeight.w500, + color: Colors.white, + ), + ), ), ), ), - ), - ), - SizedBox(width: SizeUtils.width(12)), - Expanded( - child: GestureDetector( - onTap: onFindFriends, - child: Container( - padding: EdgeInsets.symmetric(vertical: SizeUtils.height(12)), - decoration: BoxDecoration( - color: Color(0xFF2A2A2A), - borderRadius: BorderRadius.circular(SizeUtils.width(10)), + SizedBox(width: SizeUtils.width(12)), + Expanded( + child: GestureDetector( + onTap: onFindFriends, + child: Container( + padding: EdgeInsets.symmetric(vertical: SizeUtils.height(12)), + decoration: BoxDecoration( + color: Color(0xFF2A2A2A), + borderRadius: BorderRadius.circular(SizeUtils.width(10)), + ), + child: Center( + child: CustomText( + text: 'find_friends'.tr, + fontSize: SizeUtils.fontSize(14), + fontWeight: FontWeight.w500, + color: Colors.white, + ), + ), + ), ), - child: Center( - child: CustomText( - text: 'find_friends'.tr, + ), + ], + ), + SizedBox(height: SizeUtils.height(12)), + GestureDetector( + onTap: onQRCode, + child: Container( + width: double.infinity, + padding: EdgeInsets.symmetric(vertical: SizeUtils.height(12)), + decoration: BoxDecoration( + color: Color(0xFF2A2A2A), + borderRadius: BorderRadius.circular(SizeUtils.width(10)), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.qr_code, + color: Colors.white, + size: SizeUtils.fontSize(20), + ), + SizedBox(width: SizeUtils.width(8)), + CustomText( + text: 'QR Code', fontSize: SizeUtils.fontSize(14), fontWeight: FontWeight.w500, color: Colors.white, ), - ), + ], ), ), ), diff --git a/lib/media-module/widget/profile_picture.dart b/lib/media-module/widget/profile_picture.dart index ea92aec..33b86a2 100644 --- a/lib/media-module/widget/profile_picture.dart +++ b/lib/media-module/widget/profile_picture.dart @@ -3,11 +3,14 @@ import 'package:caller/media-module/widget/svgicon.dart'; import 'package:flutter/material.dart'; import 'package:caller/media-module/utils/size_config.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:image_picker/image_picker.dart'; +import 'dart:io'; import 'custom_text.dart'; -class ProfilePicture extends StatelessWidget { +class ProfilePicture extends StatefulWidget { final String imageUrl; final VoidCallback? onEditTap; + final Function(String)? onImageSelected; // Callback when image is selected final double size; final Color borderColor; @@ -15,10 +18,68 @@ class ProfilePicture extends StatelessWidget { Key? key, required this.imageUrl, this.onEditTap, + this.onImageSelected, this.size = 90, this.borderColor = Colors.blue, }) : super(key: key); + @override + State createState() => _ProfilePictureState(); +} + +class _ProfilePictureState extends State { + File? _selectedImage; + final ImagePicker _picker = ImagePicker(); + + // Method to reset to network image + void resetToNetworkImage() { + setState(() { + _selectedImage = null; + }); + } + + // Method to get current image source + bool get isUsingLocalImage => _selectedImage != null; + + // Method to get current image path + String? get currentImagePath => _selectedImage?.path; + + Future _pickImageFromGallery() async { + try { + final XFile? image = await _picker.pickImage( + source: ImageSource.gallery, + maxWidth: 800, + maxHeight: 800, + imageQuality: 85, + ); + + if (image != null) { + setState(() { + _selectedImage = File(image.path); + }); + + // Call the onImageSelected callback if provided + if (widget.onImageSelected != null) { + widget.onImageSelected!(image.path); + } + + // Call the onEditTap callback if provided + if (widget.onEditTap != null) { + widget.onEditTap!(); + } + } + } catch (e) { + print('Error picking image: $e'); + // Show error message to user + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Failed to pick image. Please try again.'), + backgroundColor: Colors.red, + ), + ); + } + } + @override Widget build(BuildContext context) { return Transform.translate( @@ -30,34 +91,35 @@ class ProfilePicture extends StatelessWidget { child: Stack( children: [ Container( - width: SizeUtils.width(size), - height: SizeUtils.width(size), + width: SizeUtils.width(widget.size), + height: SizeUtils.width(widget.size), decoration: BoxDecoration( shape: BoxShape.circle, - border: Border.all(color: borderColor, width: 3), + border: Border.all(color: widget.borderColor, width: 3), ), child: ClipOval( - child: Image.network( - imageUrl, - fit: BoxFit.cover, - errorBuilder: (context, error, stackTrace) { - return Container( - color: Colors.grey[600], - child: Icon( - Icons.person, - color: Colors.white, - size: SizeUtils.fontSize(40), + child: _selectedImage != null + ? Image.file( + _selectedImage!, + fit: BoxFit.cover, + errorBuilder: (context, error, stackTrace) { + return _buildFallbackImage(); + }, + ) + : Image.network( + widget.imageUrl, + fit: BoxFit.cover, + errorBuilder: (context, error, stackTrace) { + return _buildFallbackImage(); + }, ), - ); - }, - ), ), ), Positioned( bottom: 5, right: 18, child: GestureDetector( - onTap: onEditTap, + onTap: _pickImageFromGallery, child: Container( padding: EdgeInsets.symmetric( vertical: SizeUtils.width(4), @@ -91,4 +153,15 @@ class ProfilePicture extends StatelessWidget { ), ); } + + Widget _buildFallbackImage() { + return Container( + color: Colors.grey[600], + child: Icon( + Icons.person, + color: Colors.white, + size: SizeUtils.fontSize(40), + ), + ); + } } diff --git a/lib/translations/en_Us.dart b/lib/translations/en_Us.dart index 8bf7646..458a3b1 100644 --- a/lib/translations/en_Us.dart +++ b/lib/translations/en_Us.dart @@ -99,6 +99,59 @@ class EnUs { 'favourite_videos': 'Favourite Videos', 'loading_favourites': 'Loading favourite videos...', + // Offline Mode Screen + 'offline_mode': 'Offline Mode', + 'no_content_yet': 'No content yet', + 'cached_content_will_show_here': 'Cached content will be displayed here', + 'no_cached_content': 'No cached content for now', + 'offline_settings': 'Offline Settings', + + // Offline Settings Screen + 'offline_mode_settings': 'Offline Mode Settings', + 'videos_100': '100 videos', + 'videos_150': '150 videos', + 'videos_200': '200 videos', + 'estimated_270mb_30min': 'Estimated 270MB, playable for about 30 minutes', + 'estimated_320mb_45min': 'Estimated 320MB, playable for about 45 minutes', + 'estimated_400mb_60min': 'Estimated 400MB, playable for about 60 minutes', + 'auto_replace_wifi': + 'Automatically replace with new videos under Wi-Fi environment?', + 'clear_all': 'Clear All', + 'start_caching': 'Start Caching', + 'used_0mb_available_5gb': 'Used 0MB/Available 5GB', + 'confirm_clear_all': 'Confirm Clear', + 'confirm_clear_message': + 'Are you sure you want to clear all cached content?', + 'confirm': 'Confirm', + 'caching_started': 'Started caching', + + // Media Module - History Screen + 'watch_history': 'Watch History', + 'user': 'User', + 'video': 'Video', + 'film_tv': 'Film & TV', + 'live': 'Live', + 'edit': 'Edit', + 'within_week': 'Within a week', + 'no_watch_history': 'You don\'t have any watch history yet', + 'go_to_screening_room': + 'Go to the screening room to discover more film and television content', + 'go_to_screening_room_btn': 'Go to the screening room to take a look', + 'my_visit_record': 'My visit record (only visible to myself)', + 'mutual_follow': 'Mutual Follow', + 'followed': 'Followed', + 'return_follow': 'Return Follow', + 'works_not_seen': 'works not seen | View works>', + 'recently_watched': 'Recently Watched', + 'recently_watched_not_live': + 'Recently watched streamers have not started broadcasting yet', + 'go_to_live_channel': + 'Go to the live channel to watch more exciting live broadcasts >', + 'watched_earlier': 'Watched Earlier', + 'end_time': 'End time', + 'no_more': 'No more for now', + 'today': 'Today', + // Live Streaming Screen 'add_topic': 'Add Topic', 'search_topics': 'Search topics...', @@ -126,7 +179,6 @@ class EnUs { 'phone_gaming': 'Phone gaming', 'live_studio': 'Live Studio', 'help': 'Help', - 'live': 'LIVE', 'ps5': 'PS5', 'lms': 'LMS', 'view': 'VIEW', @@ -183,14 +235,12 @@ class EnUs { 'cancel_media': 'Cancel', 'save': 'Save', 'delete': 'Delete', - 'edit': 'Edit', 'back': 'Back', 'previous': 'Previous', 'close': 'Close', 'ok': 'OK', 'yes': 'Yes', 'no': 'No', - 'confirm': 'Confirm', 'success': 'Success', 'failed': 'Failed', 'network_error': 'Network Error', diff --git a/lib/translations/zh_CN.dart b/lib/translations/zh_CN.dart index 76615a4..9d0cc13 100644 --- a/lib/translations/zh_CN.dart +++ b/lib/translations/zh_CN.dart @@ -37,7 +37,7 @@ class ZhCn { 'report': '举报', 'chat_info': '聊天信息', // Search Screen - 'filter_by': '筛选', + 'filter_by': '按类型筛选', 'date': '日期', 'photos_and_videos': '图片和视频', 'files': '文件', @@ -46,22 +46,25 @@ class ZhCn { 'transactions': '交易', 'mini': '小程序', 'channels': '频道', - 'search_results_for': '搜索结果:', 'cancel': '取消', - 'leave_group': '离开群组', - 'group_name': '群组名称', - 'group_qr_code': '群组二维码', - 'group_notice': '群组公告', + 'search_results_for': '搜索结果:', + 'leave_group': '退出群聊', + 'group_name': '群名称', + 'group_qr_code': '群二维码', + 'group_notice': '群公告', + //moments 'moments': '朋友圈', 'like': '点赞', 'comment': '评论', + //qrcode mine 'scan_text': '扫描二维码添加我为好友', 'change_style': '更换样式', 'save_image': '保存图片', //chat info page - 'confirm_clear': '确认清除', - 'are_you_sure_clear_chat': '你确定清除聊天吗', - 'yes_clear': '是的,清楚', + 'confirm_clear': '确认清空', + 'are_you_sure_clear_chat': '确定要清空聊天记录吗', + 'yes_clear': '确定清空', + // Media Module - Navigation 'home': '首页', 'camera': '相机', @@ -95,8 +98,54 @@ class ZhCn { // Media Module - Favourite Screen 'favourite_videos': '收藏视频', 'loading_favourites': '加载收藏视频中...', - 'no_favourites': '暂无收藏视频', - 'remove_from_favourites': '从收藏中移除', + + // Offline Mode Screen + 'offline_mode': '离线模式', + 'no_content_yet': '还没有内容', + 'cached_content_will_show_here': '已缓存的内容会显示在这里', + 'no_cached_content': '暂无缓存内容', + 'offline_settings': '离线设置', + + // Offline Settings Screen + 'offline_mode_settings': '离线模式设置', + 'videos_100': '100条视频', + 'videos_150': '150条视频', + 'videos_200': '200条视频', + 'estimated_270mb_30min': '预估270MB 可播放约30分钟', + 'estimated_320mb_45min': '预估320MB 可播放约45分钟', + 'estimated_400mb_60min': '预估400MB 可播放约60分钟', + 'auto_replace_wifi': 'Wi-Fi环境下自动替换为新视频?', + 'clear_all': '全部清除', + 'start_caching': '开始缓存', + 'used_0mb_available_5gb': '已使用0MB/可用5GB', + 'confirm_clear_all': '确认清除', + 'confirm_clear_message': '确定要清除所有已缓存的内容吗?', + 'confirm': '确定', + 'caching_started': '开始缓存', + + // Media Module - History Screen + 'watch_history': '观看历史', + 'user': '用户', + 'video': '视频', + 'film_tv': '影视综', + 'live': '直播', + 'edit': '编辑', + 'within_week': '一周内', + 'no_watch_history': '你还没有任何观看记录', + 'go_to_screening_room': '去放映厅发现更多影视内容', + 'go_to_screening_room_btn': '去放映厅看看', + 'my_visit_record': '我的访问记录 (仅自己可见)', + 'mutual_follow': '互相关注', + 'followed': '已关注', + 'return_follow': '回关', + 'works_not_seen': '个作品未看 | 看作品>', + 'recently_watched': '近期常看', + 'recently_watched_not_live': '近期常看主播还没有开播', + 'go_to_live_channel': '去直播频道看更多精彩直播 >', + 'watched_earlier': '更早看过', + 'end_time': '结束时间', + 'no_more': '暂时没有更多了', + 'today': '今天', // Media Module - Information Screen 'create_story': '创建故事', @@ -134,7 +183,6 @@ class ZhCn { 'cancel_media': '取消', 'save': '保存', 'delete': '删除', - 'edit': '编辑', 'done': '完成', 'back': '返回', 'next': '下一步', @@ -143,7 +191,6 @@ class ZhCn { 'ok': '确定', 'yes': '是', 'no': '否', - 'confirm': '确认', 'success': '成功', 'failed': '失败', 'network_error': '网络错误', @@ -236,7 +283,6 @@ class ZhCn { 'phone_camera': '手机相机', 'phone_gaming': '手机游戏', 'live_studio': '直播工作室', - 'live': '直播', 'ps5': 'PS5', 'lms': 'LMS', 'view': '查看', diff --git a/pubspec.lock b/pubspec.lock index 7b4982e..65ab0dd 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -428,7 +428,7 @@ packages: source: hosted version: "3.1.2" flutter_staggered_grid_view: - dependency: "direct dev" + dependency: "direct main" description: name: flutter_staggered_grid_view sha256: "19e7abb550c96fbfeb546b23f3ff356ee7c59a019a651f8f102a4ba9b7349395" diff --git a/pubspec.yaml b/pubspec.yaml index 2447587..01664b4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -41,6 +41,7 @@ dependencies: wechat_assets_picker: ^9.5.1 image_picker: ^1.1.2 qr_flutter: ^4.1.0 + flutter_staggered_grid_view: ^0.7.0 gal: ^2.3.1 file_picker: ^10.2.0 open_filex: ^4.7.0