// Build the animation for the overall draggable dismissable content. Widget _buildAnimation(BuildContext context, Widget child) { return(Transform.translate( offset: _moveAnimation.value, child: child )); }
public override Widget buildTransitions(BuildContext context1, Animation <float> animation, Animation <float> secondaryAnimation, Widget child) { return(new OrientationBuilder( builder: (BuildContext context2, Orientation orientation) => { _lastOrientation = orientation; if (!animation.isCompleted) { bool reverse = animation.status == AnimationStatus.reverse; Rect rect = reverse ? _rectAnimatableReverse.evaluate(animation) : _rectAnimatable.evaluate(animation); Rect sheetRect = reverse ? _sheetRectAnimatableReverse.evaluate(animation) : _sheetRectAnimatable.evaluate(animation); float?sheetScale = reverse ? _sheetScaleAnimatableReverse.evaluate(animation) : _sheetScaleAnimatable.evaluate(animation); List <Widget> widgets = new List <Widget>(); widgets.Add( Positioned.fromRect( rect: sheetRect, child: new Opacity( opacity: _sheetOpacity.value, child: Transform.scale( alignment: getSheetAlignment(_contextMenuLocation), scale: sheetScale ?? 1.0f, child: new _ContextMenuSheet( key: _sheetGlobalKey, actions: _actions, contextMenuLocation: _contextMenuLocation, orientation: orientation ) ) ) ) ); widgets.Add( Positioned.fromRect( key: _childGlobalKey, rect: rect, child: _builder(context2, animation) )); return new Stack( children: widgets ); } return new _ContextMenuRouteStatic( actions: _actions, child: _builder(context1, animation), childGlobalKey: _childGlobalKey, contextMenuLocation: _contextMenuLocation, onDismiss: _onDismiss, orientation: orientation, sheetGlobalKey: _sheetGlobalKey ); } )); }
public override Widget build(BuildContext context) { Widget child = new Container( decoration: new BoxDecoration( boxShadow: new List <BoxShadow> { new BoxShadow( color: new Color(0x66000000), offset: new Offset(0, 2f), blurRadius: 4f ) }, borderRadius: BorderRadius.all(32), color: new Color(0xff000000) ), height: 64, width: 64, child: new Center( child: Transform.rotate( degree: Mathf.PI, alignment: Alignment.center, child: new Icon( Icons.MaterialExpandMore, color: new Color(0xffffffff), size: 32f ) ) ) ); if (widget._displayThreshold != null) { if (Math.Abs(_animation.value) < 1e-2) { child = null; } else { child = new Opacity( opacity: _animation.value, child: child ); } } return(new Positioned( bottom: 140, right: 48, child: new Clickable( onTap: () => widget._scrollController.animateTo( 0, SuitableAnimationTimeSpan, Curves.easeIn), child: child ) )); }
public override Widget build(int i, float animationValue, Widget widget) { Offset s = CustomLayoutUtils._getOffsetValue(values: this.values, animationValue: animationValue, index: i); return(Transform.translate( offset: s, child: widget )); }
public override Widget build(int i, float animationValue, Widget widget) { float v = CustomLayoutUtils._getValue(values: this.values, animationValue: animationValue, index: i); return(Transform.rotate( degree: v, child: widget )); }
// Build the animation for the _ContextMenuSheet. Widget _buildSheetAnimation(BuildContext context, Widget child) { return(Transform.scale( alignment: _ContextMenuRoute.getSheetAlignment(widget.contextMenuLocation), scale: _sheetScaleAnimation.value, child: new Opacity( opacity: _sheetOpacityAnimation.value, child: child ) )); }
public override Widget build(BuildContext context) { return(Transform.rotate( degree: _animation.value, alignment: Alignment.center, child: new Icon( Icons.IconFontLoading, size: widget._size, color: IconColor ) )); }
// Build the animation for the child. Widget _buildChildAnimation(BuildContext context, Widget child) { _lastScale = _getScale( widget.orientation, MediaQuery.of(context).size.height, _moveAnimation.value.dy ); return(Transform.scale( key: widget.childGlobalKey, scale: _lastScale, child: child )); }
public override Widget build(BuildContext context) { return(Transform.rotate( degree: m_Animation.value, alignment: Alignment.center, child: new Container( width: widget.size, height: widget.size, child: Image.asset( widget.isWhite ? "Images/white-loading" : "Images/black-loading" ) ) )); }
public override Widget build(BuildContext context) { return(SizedBox.fromSize(size: AppConstants.DIRECTION_BUTTON_SIZE * 2.8f, child: Transform.rotate( origin: new Offset(90, 90), degree: Mathf.PI / 4, child: new Column( mainAxisSize: MainAxisSize.min, children: new List <Widget>() { new SizedBox(height: AppConstants.DIRECTION_BUTTON_SPACE), new Row( children: new List <Widget>() { new SizedBox(width: AppConstants.DIRECTION_BUTTON_SPACE), new GBButton( size: AppConstants.DIRECTION_BUTTON_SIZE, () => { Game.of(context).Drop(); } ), new SizedBox(width: AppConstants.DIRECTION_BUTTON_SPACE), new GBButton( size: AppConstants.DIRECTION_BUTTON_SIZE, () => { Game.of(context).Right(); } ) } ), new SizedBox(height: AppConstants.DIRECTION_BUTTON_SPACE), new Row( children: new List <Widget>() { new SizedBox(width: AppConstants.DIRECTION_BUTTON_SPACE), new GBButton( size: AppConstants.DIRECTION_BUTTON_SIZE, () => { Game.of(context).Left(); } ), new SizedBox(width: AppConstants.DIRECTION_BUTTON_SPACE), new GBButton( size: AppConstants.DIRECTION_BUTTON_SIZE, () => { Game.of(context).Down(); } ) } ), new SizedBox(height: AppConstants.DIRECTION_BUTTON_SPACE) } ) ) )); }
public override Widget build(BuildContext context) { D.assert(WidgetsD.debugCheckHasDirectionality(context)); D.assert(material_.debugCheckHasMaterialLocalizations(context)); D.assert(material_.debugCheckHasMaterialLocalizations(context)); ThemeData theme = Theme.of(context); List <Widget> children = new List <Widget> { }; if (widget.accountName != null) { Widget accountNameLine = new LayoutId( id: _AccountDetailsLayout.accountName, child: new Padding( padding: EdgeInsets.symmetric(vertical: 2.0f), child: new DefaultTextStyle( style: theme.primaryTextTheme.bodyText1, overflow: TextOverflow.ellipsis, child: widget.accountName ) ) ); children.Add(accountNameLine); } if (widget.accountEmail != null) { Widget accountEmailLine = new LayoutId( id: _AccountDetailsLayout.accountEmail, child: new Padding( padding: EdgeInsets.symmetric(vertical: 2.0f), child: new DefaultTextStyle( style: theme.primaryTextTheme.bodyText2, overflow: TextOverflow.ellipsis, child: widget.accountEmail ) ) ); children.Add(accountEmailLine); } if (widget.onTap != null) { Widget dropDownIcon = new LayoutId( id: _AccountDetailsLayout.dropdownIcon, child: new SizedBox( height: UserAccountsDrawerHeaderUtils._kAccountDetailsHeight, width: UserAccountsDrawerHeaderUtils._kAccountDetailsHeight, child: new Center( child: Transform.rotate( angle: _animation.value * Mathf.PI, child: new Icon( Icons.arrow_drop_down, color: widget.arrowColor ) ) ) ) ); children.Add(dropDownIcon); } Widget accountDetails = new CustomMultiChildLayout( layoutDelegate: new _AccountDetailsLayout( Directionality.of(context)), children: children ); if (widget.onTap != null) { accountDetails = new InkWell( onTap: widget.onTap == null ? (GestureTapCallback)null : () => { widget.onTap(); }, child: accountDetails ); } return(new SizedBox( height: UserAccountsDrawerHeaderUtils._kAccountDetailsHeight, child: accountDetails )); }
public override Widget build(int i, float animationValue, Widget widget) { float s = CustomLayoutUtils._getValue(values: this.values, animationValue: animationValue, index: i); return(Transform.scale(scale: s, child: widget)); }
public override Widget build(BuildContext context) { return(new GestureDetector ( onLongPressDragUpdate: details => { // Debug.Log("onLongPressDragUpdate"); }, onScaleStart: details => { MoveEndVelocity = Offset.zero; previousScrollPosition = details.focalPoint; previousDragPosition = details.focalPoint; }, onScaleUpdate: details => { // Debug.Log("onScaleUpdate"); MoveEndVelocity = Offset.zero; float scaleDiff = previousScale * (details.scale - 1); if (aimedScale >= widget.MaxScale && scaleDiff > 0) { scaleDiff = 0; } if (aimedScale <= widget.MinScale && scaleDiff < 0) { scaleDiff = 0; } scroll(details.focalPoint, scaleDiff); move(details.focalPoint); // postCheck(); }, onScaleEnd: details => { MoveEndVelocity = details.velocity.pixelsPerSecond; }, onVerticalDragStart: details => { MoveEndVelocity = Offset.zero; previousScrollPosition = details.globalPosition; previousDragPosition = details.globalPosition; }, onVerticalDragUpdate: details => { // Debug.Log("onVerticalDragUpdate"); if (details.isScroll) { float scaleDiff = details.delta.dy / MediaQuery.of(context).size.height; if (aimedScale >= widget.MaxScale && scaleDiff > 0) { scaleDiff = 0; } if (aimedScale <= widget.MinScale && scaleDiff < 0) { scaleDiff = 0; } if (Math.Abs(scaleDiff) > float.Epsilon) { scroll(details.globalPosition, scaleDiff); } // postCheck(); } else { move(details.globalPosition); // postCheck(); } }, onVerticalDragEnd: details => { MoveEndVelocity = details.velocity.pixelsPerSecond; }, child: new ClipRect ( clipBehavior: Clip.hardEdge, child: new Stack ( children: new List <Widget> { new Positioned ( left: Offset.dx, top: Offset.dy, child: Transform.scale ( scale: Scale, child: new Container( key: ContentViewContainerKey, width: widget.ContentSizeWidth, height: widget.ContentSizeHeight, child: widget.child ), alignment: Alignment.topLeft ) ) } ) ) )); }
Widget _buildContent(BuildContext context) { var articleIds = this.widget.viewModel.team.articleIds; var articlesHasMore = this.widget.viewModel.team.articlesHasMore ?? false; var teamArticleLoading = this.widget.viewModel.teamArticleLoading && articleIds == null; int itemCount; if (teamArticleLoading) { itemCount = 3; } else { if (articleIds == null) { itemCount = 3; } else { var articleCount = articlesHasMore ? articleIds.Count : articleIds.Count + 1; itemCount = 2 + (articleIds.Count == 0 ? 1 : articleCount); } } return(new Container( color: CColors.Background, child: new CustomScrollbar( new SmartRefresher( controller: this._refreshController, enablePullDown: false, enablePullUp: articlesHasMore, onRefresh: this._onRefresh, onNotification: this._onNotification, child: ListView.builder( physics: new AlwaysScrollableScrollPhysics(), itemCount: itemCount, itemBuilder: (cxt, index) => { if (index == 0) { return Transform.scale( scale: this._factor, child: this._buildTeamInfo() ); } if (index == 1) { return _buildTeamArticleTitle(); } if (teamArticleLoading && index == 2) { var height = MediaQuery.of(context: context).size.height - headerHeight - 44; return new Container( height: height, child: new GlobalLoading() ); } if ((articleIds == null || articleIds.Count == 0) && index == 2) { var height = MediaQuery.of(context: context).size.height - headerHeight - 44; return new Container( height: height, child: new BlankView( "哎呀,暂无已发布的文章", "image/default-article" ) ); } if (index == itemCount - 1 && !articlesHasMore) { return new EndView(); } var articleId = articleIds[index - 2]; if (!this.widget.viewModel.articleDict.ContainsKey(key: articleId)) { return new Container(); } var article = this.widget.viewModel.articleDict[key: articleId]; return new ArticleCard( article: article, () => this.widget.actionModel.pushToArticleDetail(obj: article.id), () => this._share(article: article), fullName: this.widget.viewModel.team.name, key: new ObjectKey(value: article.id) ); } ) ) ) )); }
Widget _buildUserContent(BuildContext context) { var articleIds = this.widget.viewModel.user.articleIds; var articlesHasMore = this.widget.viewModel.user.articlesHasMore ?? false; var userArticleLoading = this.widget.viewModel.userArticleLoading && articleIds == null; int itemCount; if (userArticleLoading) { itemCount = 3; } else { if (articleIds == null) { itemCount = 3; } else { var articleCount = articlesHasMore ? articleIds.Count : articleIds.Count + 1; itemCount = 2 + (articleIds.Count == 0 ? 1 : articleCount); } } return(new Container( color: CColors.Background, child: new CustomScrollbar( new SmartRefresher( controller: this._refreshController, enablePullDown: false, enablePullUp: articlesHasMore, onRefresh: this._onRefresh, onNotification: this._onNotification, child: ListView.builder( physics: new AlwaysScrollableScrollPhysics(), itemCount: itemCount, itemBuilder: (cxt, index) => { if (index == 0) { return Transform.scale( scale: this._factor, child: this._buildUserInfo() ); } if (index == 1) { return _buildUserArticleTitle(); } if (userArticleLoading && index == 2) { var height = MediaQuery.of(context: context).size.height - headerHeight - 44; return new Container( height: height, child: new GlobalLoading() ); } if ((articleIds == null || articleIds.Count == 0) && index == 2) { var height = MediaQuery.of(context: context).size.height - headerHeight - 44; return new Container( height: height, child: new BlankView( "哎呀,暂无已发布的文章", "image/default-article" ) ); } if (index == itemCount - 1 && !articlesHasMore) { return new EndView(); } var articleId = articleIds[index - 2]; if (!this.widget.viewModel.articleDict.ContainsKey(key: articleId)) { return new Container(); } var article = this.widget.viewModel.articleDict[key: articleId]; var linkUrl = CStringUtils.JointProjectShareLink(projectId: article.id); return new ArticleCard( article: article, () => this.widget.actionModel.pushToArticleDetail(obj: article.id), () => ShareManager.showArticleShareView( this.widget.viewModel.currentUserId != article.userId, isLoggedIn: this.widget.viewModel.isLoggedIn, () => { Clipboard.setData(new ClipboardData(text: linkUrl)); CustomDialogUtils.showToast("复制链接成功", Icons.check_circle_outline); }, () => this.widget.actionModel.pushToLogin(), () => this.widget.actionModel.pushToBlock(article.id), () => this.widget.actionModel.pushToReport(article.id, ReportType.article), type => { CustomDialogUtils.showCustomDialog( child: new CustomLoadingDialog() ); string imageUrl = CImageUtils.SizeTo200ImageUrl(article.thumbnail.url); this.widget.actionModel.shareToWechat(arg1: type, arg2: article.title, arg3: article.subTitle, arg4: linkUrl, arg5: imageUrl) .Then(onResolved: CustomDialogUtils.hiddenCustomDialog) .Catch(_ => CustomDialogUtils.hiddenCustomDialog()); }, () => this.widget.actionModel.mainRouterPop() ), this.widget.viewModel.user.fullName ?? this.widget.viewModel.user.name, key: new ObjectKey(value: article.id) ); } ) ) ) )); }
public override Widget build(BuildContext context) { var screenSize = MediaQuery.of(context).size; var screenWidth = screenSize.width; var screenHeight = screenSize.height; var headerChildren = new List <Widget> { new Expanded( child: new Text( $"{channel?.name ?? string.Empty}", style: new TextStyle( fontSize: 16, fontWeight: FontWeight.w500, color: new Color(0xff212121), fontFamily: "PingFang" ) ) ), }; headerChildren.Add( new GestureDetector( onTap: () => { if (screenWidth < 750) { m_AnimationController.reverse(); } else { HomePage.of(this.context).HideChannelInfo(); } }, child: new Icon( IconFont.IconFontClose, color: new Color(0xff979a9e), size: 28 ) ) ); var children = new List <Widget> { }; if (channel == null) { children.Add( new Loading(size: 56) ); } else { children.Add( CreateLobbyIcon( channel.thumbnail, size: 184, radius: 4 ) ); children.Add( new Container( margin: EdgeInsets.only(top: 32), child: new Text( channel.name, style: new TextStyle( color: new Color(0xff000000), fontSize: 24, fontWeight: FontWeight.bold ) ) ) ); children.Add( new Container( margin: EdgeInsets.only(top: 8), child: new Text( $"{channel.memberCount}成员", style: new TextStyle( color: new Color(0xff797979), fontSize: 14 ) ) ) ); var topic = channel.topic; if (!channel.groupId.IsNullOrEmpty() && group != null) { topic = group.description; } children.Add( new Container( margin: EdgeInsets.only(top: 32), child: new Text( topic, style: new TextStyle( color: new Color(0xff000000), fontSize: 14 ) ) ) ); var buttonChildren = new List <Widget>(); if (m_Joining) { buttonChildren.Add( new Text( "加入群聊", style: new TextStyle( color: new Color(0x00000000), fontSize: 18, fontFamily: "PingFang" ) ) ); buttonChildren.Add( new Loading( size: 24 ) ); } else { buttonChildren.Add( new Text( "加入群聊", style: new TextStyle( fontSize: 18, color: new Color(0xff2196f3), fontFamily: "PingFang" ) ) ); } children.Add( new GestureDetector( onTap: () => { if (m_Joining) { return; } setState(() => m_Joining = true); var requestUrl = string.IsNullOrEmpty(channel.groupId) ? $"/api/connectapp/v1/channels/{channel.id}/join" : $"/api/connectapp/v1/groups/{channel.groupId}/join"; Utils.Post <JoinChannelResponse>( requestUrl, "{}" ).Then(response => { using (WindowProvider.of(context).getScope()) { if (mounted) { var state = HomePage.of(context); var responseChannel = response.channel; state.AddChannel(responseChannel); state.Select(responseChannel.id); state.Ack(responseChannel.id); setState(() => m_Joining = false); } } }); }, child: new Container( height: 56, width: 234, margin: EdgeInsets.only(top: 48), decoration: new BoxDecoration( color: new Color(0xffffffff), borderRadius: BorderRadius.circular(6), border: Border.all( color: new Color(0xff2196f3) ) ), alignment: Alignment.center, child: new Stack( alignment: Alignment.center, children: buttonChildren ) ) ) ); } Widget all = new Container( color: new Color(0xffffffff), child: new Scroller( child: new SingleChildScrollView( child: new Column( children: new List <Widget> { new Container( height: 64, decoration: new BoxDecoration( border: new Border( bottom: new BorderSide( color: new Color(0xffd8d8d8) ) ) ), padding: EdgeInsets.symmetric(horizontal: 24), alignment: Alignment.center, child: new Row( crossAxisAlignment: CrossAxisAlignment.center, children: headerChildren ) ), new Container( constraints: new BoxConstraints( minHeight: screenHeight - 64 ), width: screenWidth < 750 ? (float?)null : 450, margin: EdgeInsets.symmetric(horizontal: 24), alignment: Alignment.center, child: new Column( children: children ) ), } ) ) ) ); var stacked = new List <Widget> { all }; all = new Stack( children: stacked ); if (screenWidth < 750) { all = Transform.translate( offset: new Offset(0, (1 - m_AnimationController.value) * screenHeight), child: all ); } return(all); }
public override Widget build(BuildContext context) { var channel = widget.channels[widget.selectedChannelId]; Widget members; var screenSize = MediaQuery.of(context).size; var screenWidth = screenSize.width; var screenHeight = screenSize.height; var containerWidth = screenWidth - 48; if (screenWidth >= 750) { containerWidth -= 375; } var countPerRow = (containerWidth / 240).floor(); var rowCount = ((widget.members.ContainsKey(channel.id) ? widget.members[channel.id].Count : 0) / (float)countPerRow).ceil(); if (!widget.hasMoreMembers.ContainsKey(widget.selectedChannelId)) { widget.hasMoreMembers[widget.selectedChannelId] = true; } if (widget.hasMoreMembers[widget.selectedChannelId]) { rowCount += 1; } members = new SliverList( del: new SliverChildBuilderDelegate( builder: (buildContext, index) => { if (widget.hasMoreMembers[widget.selectedChannelId] && index == rowCount - 1) { return(new Container( height: 78, alignment: Alignment.center, child: new LoadTrigger( onLoad: () => { var offset = widget.members.ContainsKey(channel.id) ? widget.members[channel.id].Count : 0; Utils.Get <GetMembersResponse>( $"/api/connectapp/channels/{channel.id}/members?offset={offset}" ).Then(response => { response.list.ForEach(member => { if (widget.members[channel.id].All(m => m.user.id != member.user.id)) { widget.members[channel.id].Add(member); } widget.users.putIfAbsent(member.user.id, () => member.user); }); m_AmIOwner = widget.members[channel.id].Any(member => member.user.id == Window.currentUserId && member.role == "owner"); widget.hasMoreMembers[widget.selectedChannelId] = response.total > widget.members[channel.id].Count; if (mounted) { using (WindowProvider.of(context).getScope()) { setState(() => { }); } } }); } ) )); } var children = new List <Widget> { }; for (var i = 0; i < countPerRow; ++i) { if (index * countPerRow + i < widget.members[channel.id].Count) { var member = widget.members[channel.id][index * countPerRow + i]; children.Add( new Expanded( child: new Container( height: 78, width: 240, alignment: Alignment.center, child: new Container( height: 50, padding: EdgeInsets.only( top: 6, bottom: 4 ), child: new Row( children: new List <Widget> { new Container( margin: EdgeInsets.only(right: 8), child: new Avatar(member.user) ), new Expanded( child: new Column( crossAxisAlignment: CrossAxisAlignment.start, children: new List <Widget> { new Text( member.user.fullName, style: new TextStyle( fontSize: 14, fontWeight: FontWeight.w500, fontFamily: "PingFang" ), overflow: TextOverflow.ellipsis ), new Text( member.user.title ?? string.Empty, style: new TextStyle( color: new Color(0xff5a5a5b), fontSize: 14, fontFamily: "PingFang" ), overflow: TextOverflow.ellipsis ) } ) ) } ) ) ) ) ); } else { children.Add( new Expanded( child: new Container( height: 78, width: 240 ) ) ); } } return(new Container( margin: EdgeInsets.symmetric(horizontal: 24), decoration: new BoxDecoration( border: new Border( top: new BorderSide( color: new Color(0xfff0f0f0) ) ) ), child: new Row( mainAxisAlignment: MainAxisAlignment.start, children: children ) )); }, childCount: rowCount ) ); var headerChildren = new List <Widget> { new Expanded( child: new Text( $"{channel.name}", style: new TextStyle( fontSize: 16, fontWeight: FontWeight.w500, color: new Color(0xff212121), fontFamily: "PingFang" ) ) ), }; headerChildren.Add( new GestureDetector( onTap: () => { if (screenWidth < 750) { m_AnimationController.reverse(); } else { HomePage.of(this.context).HideChannelInfo(); } }, child: new Icon( IconFont.IconFontClose, color: new Color(0xff979a9e), size: 28 ) ) ); Widget all = new Container( color: new Color(0xffffffff), child: new Scroller( child: new CustomScrollView( slivers: new List <Widget> { new SliverToBoxAdapter( child: new Container( height: 64, decoration: new BoxDecoration( border: new Border( bottom: new BorderSide( color: new Color(0xffd8d8d8) ) ) ), padding: EdgeInsets.symmetric(horizontal: 24), alignment: Alignment.center, child: new Row( crossAxisAlignment: CrossAxisAlignment.center, children: headerChildren ) ) ), MediaQuery.of(context).size.width < 750 ? BuildNarrowInfo() : BuildWideInfo(), new SliverToBoxAdapter( child: new Container( decoration: new BoxDecoration( border: new Border( top: new BorderSide( color: new Color(0xffd8d8d8) ), bottom: new BorderSide( color: new Color(0xffd8d8d8) ) ) ), padding: EdgeInsets.symmetric(vertical: 18), margin: EdgeInsets.symmetric(horizontal: 24), height: 78, child: new Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: new List <Widget> { new Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: new List <Widget> { new Text( "消息免打扰", style: new TextStyle( fontSize: 14, color: new Color(0xff212121), fontFamily: "PingFang" ) ), new Text( "打开后,将不会收到消息提醒", style: new TextStyle( fontSize: 14, color: new Color(0xff797979), fontFamily: "PingFang" ) ), } ), new Switch( m_MuteController ) } ) ) ), new SliverToBoxAdapter( child: new Container( decoration: new BoxDecoration( border: new Border( bottom: new BorderSide( color: new Color(0xffd8d8d8) ) ) ), padding: EdgeInsets.symmetric(vertical: 18), margin: EdgeInsets.symmetric(horizontal: 24), height: 78, child: new Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: new List <Widget> { new Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: new List <Widget> { new Text( "设为置顶", style: new TextStyle( fontSize: 14, color: new Color(0xff212121), fontFamily: "PingFang" ) ), new Text( "打开后,当前群聊将会被置顶在群聊列表", style: new TextStyle( fontSize: 14, color: new Color(0xff797979), fontFamily: "PingFang" ) ) } ), new Switch( m_PinController ) } ) ) ), new SliverToBoxAdapter( child: new Container( margin: EdgeInsets.only(top: 24, left: 24, right: 24), padding: EdgeInsets.only(bottom: 8), child: new Text( $"群聊成员({channel.memberCount})", style: new TextStyle( fontSize: 18, fontWeight: FontWeight.w500, fontFamily: "PingFang" ) ) ) ), members, new SliverToBoxAdapter( child: new Container( height: 56 ) ) } ) ) ); var stacked = new List <Widget> { all }; if (!m_AmIOwner) { var quitButtonChildren = new List <Widget>(); if (m_Quiting) { quitButtonChildren.Add( new Text( "退出群聊", style: new TextStyle( fontSize: 18, color: new Color(0x00000000), fontFamily: "PingFang" ) ) ); quitButtonChildren.Add( new Loading( size: 24 ) ); } else { quitButtonChildren.Add(new Text( "退出群聊", style: new TextStyle( fontSize: 18, color: new Color(0xfff44336), fontFamily: "PingFang" ) ) ); } stacked.Add( new Positioned( bottom: 0, left: 0, right: 0, child: new GestureDetector( onTap: () => { if (m_Quiting) { return; } setState(() => m_Quiting = true); var requestUrl = string.IsNullOrEmpty(channel.groupId) ? $"/api/connectapp/v1/channels/{channel.id}/leave" : $"/api/connectapp/v1/groups/{channel.groupId}/leave"; var state = HomePage.of(context); Utils.Post <Models.Channel>( requestUrl, "{}" ).Then(c => { state.Select(string.Empty); state.RemoveChannel(channel); }); }, child: new Container( height: 56, decoration: new BoxDecoration( color: new Color(0xffffffff), border: new Border( top: new BorderSide( color: new Color(0xffd8d8d8) ) ) ), alignment: Alignment.center, child: new Stack( children: quitButtonChildren ) ) ) ) ); } all = new Stack( children: stacked ); if (screenWidth < 750) { all = Transform.translate( offset: new Offset(0, (1 - m_AnimationController.value) * screenHeight), child: all ); } return(all); }
public override Widget build(BuildContext context) { var screenWidth = MediaQuery.of(context).size.width; var windowChildren = new List <Widget> { new Scroller( child: ListView.builder( controller: m_ScrollController, reverse: true, itemCount: m_HasMoreOld ? widget.messages[widget.channel.id].Count + 1 : widget.messages[widget.channel.id].Count, itemBuilder: (ctx, index) => { if (!m_Initialized) { return(new Container()); } if (index == widget.messages[widget.channel.id].Count) { return(new LoadTrigger( () => { var lastMessageId = widget.messages[widget.channel.id].last().id; Get( $"/api/connectapp/v1/channels/{widget.channel.id}/messages?before={lastMessageId}", (GetMessagesResponse getMessagesResponse) => { if (mounted) { using (WindowProvider.of(context) .getScope()) { setState(() => { widget.messages[widget.channel.id] .AddRange( getMessagesResponse.items .Where( item => item.id != lastMessageId ) ); m_MsgsUnreads = 0; m_HasMoreUnreads = true; if (m_PreviousLastMsgId == null) { m_HasMoreUnreads = false; } else { foreach (var m in widget.messages[widget.channel.id]) { if (string.Compare(m.id, m_PreviousLastMsgId) > 0) { ++m_MsgsUnreads; } else { m_HasMoreUnreads = false; break; } } } m_HasMoreOld = getMessagesResponse.hasMore; }); } } }); } )); } var currentMessage = widget.messages[widget.channel.id][index]; var msgTime = ExtractTimeFromSnowflakeId(currentMessage.id.IsNullOrEmpty() ? currentMessage.nonce : currentMessage.id); bool showTime; var isNew = false; if (index == widget.messages[widget.channel.id].Count - 1) { showTime = true; } else { var nextMessage = widget.messages[widget.channel.id][index + 1]; showTime = msgTime - ExtractTimeFromSnowflakeId( nextMessage.id.IsNullOrEmpty() ? nextMessage.nonce : nextMessage.id) > TimeSpan.FromMinutes(5); if (nextMessage.id != null && nextMessage.id == m_PreviousLastMsgId) { isNew = true; } } Action onBuild = null; if (currentMessage.id == m_PreviousLastMsgId) { onBuild = () => { SchedulerBinding.instance.addPostFrameCallback(value => { setState(() => { m_MsgsUnreads = 0; m_HasMoreUnreads = false; }); }); }; } return(new Message( widget.messages[widget.channel.id][index], widget.users, showTime, m_PreviousLastMsgId != widget.channel.lastMessage.id && isNew, msgTime, onBuild )); } ) ), }; if (Window.reconnecting) { windowChildren.Add( new Positioned( left: 0, top: 0, right: 0, child: new Container( color: new Color(0xfffde1df), height: 48, alignment: Alignment.center, child: new Text( "网络未连接,正在连接中", style: new TextStyle( fontSize: 16, color: new Color(0xfff44336), fontFamily: "PingFang" ) ) ) ) ); } var newMsgsCount = Window.NewMessages.Count(msg => msg.author.id != Window.currentUserId); if (newMsgsCount != 0) { windowChildren.Add( new Positioned( bottom: 24, child: new GestureDetector( onTap: () => { Window.NewMessages.ForEach(msg => { Window.Messages[msg.channelId].Insert(0, msg); }); Window.NewMessages.Clear(); setState(); m_ScrollController.animateTo( 0, new TimeSpan(0, 0, 0, 0, 480), Curves.easeInOut ); }, child: new Container( height: 40, padding: EdgeInsets.symmetric(horizontal: 16), decoration: new BoxDecoration( borderRadius: BorderRadius.all(20), boxShadow: new List <BoxShadow> { new BoxShadow( offset: new Offset(0, 1), blurRadius: 6, color: new Color(0x19000000) ), }, color: new Color(0xffffffff) ), child: new Row( mainAxisAlignment: MainAxisAlignment.center, children: new List <Widget> { new Text( $"{newMsgsCount}条新消息未读", style: new TextStyle( color: new Color(0xff2196f3), fontSize: 14, fontFamily: "PingFang" ) ), } ) ) ) ) ); } if (m_MsgsUnreads > 0) { var text = $"{m_MsgsUnreads}"; if (m_HasMoreUnreads) { text += "+"; } text += "条新消息"; windowChildren.Add( new Positioned( top: 24, child: new GestureDetector( onTap: () => { var totalHeight = 0.0f; for (var index = 0; index < widget.messages[widget.channel.id].Count; ++index) { var message = widget.messages[widget.channel.id][index]; if (string.Compare(message.id, m_PreviousLastMsgId) > 0) { var showTime = true; var msgTime = ExtractTimeFromSnowflakeId(message.id.IsNullOrEmpty() ? message.nonce : message.id); if (index != widget.messages[widget.channel.id].Count - 1) { var nextMessage = widget.messages[widget.channel.id][index + 1]; showTime = msgTime - ExtractTimeFromSnowflakeId( nextMessage.id.IsNullOrEmpty() ? nextMessage.nonce : nextMessage.id) > TimeSpan.FromMinutes(5); } var layoutWidth = screenWidth * 0.7f; if (screenWidth >= 750) { layoutWidth -= 286.5f; } else { layoutWidth -= 24f; } totalHeight += CalculateMessageHeight( message, showTime, layoutWidth ); } else { break; } } if (m_HasMoreUnreads) { totalHeight += 40; } else { totalHeight += 36; } m_ScrollController.animateTo( totalHeight - MediaQuery.of(context).size.height + 184, new TimeSpan(0, 0, 0, 0, 480), Curves.easeInOut ); if (!m_HasMoreUnreads) { setState(() => { m_MsgsUnreads = 0; m_HasMoreUnreads = false; }); } }, child: new Container( height: 40, padding: EdgeInsets.symmetric(horizontal: 16), decoration: new BoxDecoration( borderRadius: BorderRadius.all(20), boxShadow: new List <BoxShadow> { new BoxShadow( offset: new Offset(0, 1), blurRadius: 6, color: new Color(0x19000000) ), }, color: new Color(0xffffffff) ), child: new Row( mainAxisAlignment: MainAxisAlignment.center, children: new List <Widget> { new Text( text, style: new TextStyle( color: new Color(0xff2196f3), fontSize: 14, fontFamily: "PingFang" ) ), new Container( margin: EdgeInsets.only(left: 4), child: Transform.rotate( child: new Icon( IconFont.IconFontArrowUp, size: 24, color: new Color(0xff2196f3) ) ) ) } ) ) ) ) ); } var rootState = HomePage.of(context); var children = new List <Widget> { new Container( color: new Color(0xffffffff), child: new Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: new List <Widget> { new ChattingWindowHeader( widget.channel, () => { if (screenWidth < 750) { m_AnimationController.reverse(); } else { HomePage.of(context).Select(string.Empty); } }), new Expanded( child: new Stack( alignment: Alignment.center, children: windowChildren ) ), new Sender( m_SenderFocusNode, widget.users), } ) ), }; if (!m_Initialized) { children.Add( new Container( alignment: Alignment.center, child: new Loading(size: 56) ) ); } Widget all = new GestureDetector( onTap: () => { FocusScope.of(context).requestFocus(m_EmptyFocusNode); }, child: new Stack( children: children ) ); if (screenWidth < 750) { all = Transform.translate( offset: new Offset((1 - m_AnimationController.value) * screenWidth, 0), child: all ); } return(all); }
public override Widget build(BuildContext context) { var screenWidth = MediaQuery.of(context).size.width; var headerChildren = new List <Widget> { new Text( "发现群聊", style: HeaderTextStyle ) }; if (screenWidth < 750) { headerChildren.Insert( 0, new GestureDetector( onTap: () => m_AnimationController.reverse(), child: new Container( width: 28, height: 28, margin: EdgeInsets.only(right: 12), child: new Icon( IconFont.IconFontArrowBack, size: 28, color: new Color(0xff979a9e) ) ) ) ); } var children = new List <Widget> { new Container( height: 64, padding: HeaderTextPadding, alignment: Alignment.centerLeft, decoration: new BoxDecoration( border: new Border( bottom: new BorderSide( color: new Color(0xffd8d8d8), width: 1 ) ) ), child: new Row( children: headerChildren ) ), }; if (widget.channels == null || widget.channels.Count == 0) { children.Add( new Expanded( child: new Container( alignment: Alignment.center, child: new Loading( size: 56 ) ) ) ); } else { var canvasWidth = screenWidth - 64; if (screenWidth >= 750) { canvasWidth -= 375; } var countPerRow = (canvasWidth / 316).floor(); var itemWidth = canvasWidth / (float)countPerRow - 16; var rowCount = (widget.channels.Count / (float)countPerRow).ceil(); var rows = new List <Widget> { }; for (var i = 0; i < rowCount; ++i) { var items = new List <Widget> { }; for (var j = 0; j < countPerRow && i * countPerRow + j < widget.channels.Count; ++j) { items.Add( new SquareLobbyCard( widget.channels.Values.ToArray()[i * countPerRow + j], widget.channels, widget.groups, itemWidth ) ); } rows.Add( new Row( mainAxisAlignment: MainAxisAlignment.start, children: items ) ); } children.Add( new Expanded( child: new Scroller( child: new SingleChildScrollView( child: new Container( padding: EdgeInsets.all(32), child: new Column( children: rows ) ) ) ) ) ); } Widget all = new Container( color: HeaderBackgroundColor, child: new Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: children ) ); if (screenWidth < 750) { all = Transform.translate( offset: new Offset((1 - m_AnimationController.value) * screenWidth, 0), child: all ); } return(all); }