Example #1
0
        public static float CalculateTextHeight(string content, float width)
        {
            var contentHeight = CTextUtils.CalculateTextHeight(text: content, textStyle: _contentStyle,
                                                               width - _contentPadding.horizontal);

            return(_contentPadding.vertical + contentHeight);
        }
Example #2
0
        public static float CalculateTextHeight(string content, float width)
        {
            var contentHeight = CTextUtils.CalculateTextHeight(
                text: MessageUtils.truncateMessage(content),
                textStyle: _contentStyle,
                textWidth: width - _contentPadding.horizontal);

            return(_contentPadding.vertical + contentHeight);
        }
Example #3
0
        public static float CalculateTextHeight(ChannelMessageView message, float width)
        {
            var attachment      = message.attachments.first();
            var fileTitleHeight = CTextUtils.CalculateTextHeight(text: attachment.filename, textStyle: _fileTitleStyle,
                                                                 width - _filePadding.horizontal - 42 - 16);
            var fileSizeHeight = CTextUtils.CalculateTextHeight(CStringUtils.FileSize(bytes: attachment.size),
                                                                textStyle: _fileSizeStyle, width - _filePadding.horizontal - 42 - 16);

            return(_filePadding.vertical + fileTitleHeight + fileSizeHeight + 4);
        }
Example #4
0
        float _getTipMenuHeight(BuildContext context)
        {
            if (this.tipMenuItems == null || this.tipMenuItems.Count == 0)
            {
                return(0);
            }

            var width      = MediaQuery.of(context: context).size.width;
            var textHeight = CTextUtils.CalculateTextHeight(
                this.tipMenuItems.FirstOrDefault()?.title ?? "",
                textStyle: CustomTextSelectionControlsUtils._kToolbarButtonFontStyle,
                textWidth: width,
                1
                );

            return(textHeight + 20);
        }
Example #5
0
        public static float CalculateTextHeight(ChannelMessageView message, float width)
        {
            var contentHeight = CTextUtils.CalculateTextHeight(
                text: MessageUtils.truncateMessage(message.content),
                textStyle: _contentStyle,
                textWidth: width - _contentPadding.horizontal);
            float descriptionHeight;

            if (message.type == ChannelMessageType.embedImage)
            {
                descriptionHeight = ImageMessage.CalculateTextHeight(message: message);
            }
            else if (message.type == ChannelMessageType.embedExternal)
            {
                var embedData            = message.embeds[0].embedData;
                var embedDataTitleHeight = CTextUtils.CalculateTextHeight(text: embedData.title,
                                                                          textStyle: _embedTitleStyle, width - 48);
                var embedDescriptionHeight = CTextUtils.CalculateTextHeight(text: embedData.description,
                                                                            textStyle: _embedDescriptionStyle, width - 48, 4);
                float embedNameHeight;
                if (embedData.image.isEmpty() && embedData.name.isEmpty())
                {
                    embedNameHeight = 0;
                }
                else
                {
                    embedNameHeight = 22;
                }

                descriptionHeight = embedDataTitleHeight + 4 + embedDescriptionHeight + 4 + embedNameHeight;
            }
            else
            {
                descriptionHeight = 0;
            }

            return(contentHeight + descriptionHeight + _contentPadding.vertical + _contentPadding.vertical);
        }
Example #6
0
        public override Widget build(BuildContext context)
        {
            var children = new List <Widget>();

            if (this.title.isNotEmpty())
            {
                children.Add(
                    new Container(
                        padding: EdgeInsets.only(16, 24, 16, this.message == null ? 24 : 8),
                        alignment: Alignment.center,
                        child: new Text(
                            data: this.title,
                            style: CTextStyle.PLargeMedium,
                            textAlign: TextAlign.center
                            )
                        ));
            }

            if (this.message.isNotEmpty())
            {
                var mediaQuery        = MediaQuery.of(context: context);
                var horizontalPadding = mediaQuery.viewInsets.left + mediaQuery.viewInsets.right + 40 + 40;
                var width             = mediaQuery.size.width - horizontalPadding - 32;
                var maxHeight         = CTextUtils.CalculateTextHeight(
                    text: this.message, textStyle: this._messageStyle, textWidth: width, 7);
                var totalHeight = CTextUtils.CalculateTextHeight(
                    text: this.message, textStyle: this._messageStyle, textWidth: width);
                if (maxHeight < totalHeight)
                {
                    maxHeight += 16;
                }
                else
                {
                    maxHeight += 32;
                }

                children.Add(new Container(
                                 height: maxHeight,
                                 alignment: Alignment.center,
                                 child: new CustomScrollbar(
                                     new SingleChildScrollView(
                                         child: new Padding(
                                             padding: EdgeInsets.only(16, 8, 16, 16),
                                             child: new Text(
                                                 data: this.message,
                                                 style: this._messageStyle
                                                 )
                                             )
                                         )
                                     )
                                 ));
            }

            if (this.actions != null)
            {
                children.Add(new CustomDivider(
                                 height: 1
                                 ));

                var _children = new List <Widget>();
                foreach (var _child in this.actions)
                {
                    _children.Add(new Expanded(
                                      child: new Stack(
                                          fit: StackFit.expand,
                                          children: new List <Widget> {
                        _child
                    }
                                          )
                                      ));
                    var index = this.actions.IndexOf(_child);
                    if (index < this.actions.Count - 1)
                    {
                        _children.Add(new Container(
                                          width: 1,
                                          color: CColors.Separator
                                          ));
                    }
                }

                Widget child = new Container(
                    height: 48,
                    child: new Row(
                        mainAxisAlignment: MainAxisAlignment.start,
                        children: _children
                        )
                    );
                children.Add(item: child);
            }

            Widget dialogChild = new IntrinsicWidth(
                child: new Column(
                    mainAxisSize: MainAxisSize.min,
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    children: children
                    )
                );

            return(new CustomDialog(
                       backgroundColor: CColors.White,
                       radius: 5,
                       child: dialogChild
                       ));
        }
Example #7
0
        IEnumerable <Widget> _buildComments(BuildContext context)
        {
            List <string> channelComments = new List <string>();

            if (this.widget.viewModel.channelMessageList.ContainsKey(this._article.channelId))
            {
                channelComments = this.widget.viewModel.channelMessageList[this._article.channelId];
            }
            var mediaQuery = MediaQuery.of(context);
            var comments   = new List <Widget> {
                new Container(
                    color: CColors.White,
                    width: mediaQuery.size.width,
                    padding: EdgeInsets.only(16, 16, 16),
                    child: new Text(
                        "评论",
                        style: CTextStyle.H5,
                        textAlign: TextAlign.left
                        )
                    )
            };

            var titleHeight = CTextUtils.CalculateTextHeight(
                "评论",
                CTextStyle.H5,
                mediaQuery.size.width - 16 * 2, // 16 is horizontal padding
                null
                ) + 16;                         // 16 is top padding

            var height = mediaQuery.size.height - navBarHeight - 44 - mediaQuery.padding.vertical;

            if (channelComments.Count == 0)
            {
                var blankView = new Container(
                    height: height - titleHeight,
                    child: new BlankView(
                        "快来写下第一条评论吧",
                        "image/default-comment"
                        )
                    );
                comments.Add(item: blankView);
                return(comments);
            }

            var   messageDict    = this.widget.viewModel.channelMessageDict[this._article.channelId];
            float contentHeights = 0;

            foreach (var commentId in channelComments)
            {
                if (!messageDict.ContainsKey(commentId))
                {
                    break;
                }

                var  message    = messageDict[commentId];
                bool isPraised  = _isPraised(message, this.widget.viewModel.loginUserId);
                var  parentName = "";
                if (message.parentMessageId.isNotEmpty())
                {
                    if (messageDict.ContainsKey(message.parentMessageId))
                    {
                        var parentMessage = messageDict[message.parentMessageId];
                        parentName = parentMessage.author.fullName;
                    }
                }

                var content = MessageUtils.AnalyzeMessage(message.content, message.mentions,
                                                          message.mentionEveryone) + (parentName.isEmpty() ? "" : $"回复@{parentName}");
                var contentHeight = CTextUtils.CalculateTextHeight(
                    content,
                    CTextStyle.PLargeBody,
                    // 16 is horizontal padding, 24 is avatar size, 8 is content left margin to avatar
                    mediaQuery.size.width - 16 * 2 - 24 - 8,
                    null
                    ) + 16 + 24 + 3 + 5 + 22 + 12;
                // 16 is top padding, 24 is avatar size, 3 is content top margin to avatar, 5 is content bottom margin to commentTime
                // 22 is commentTime height, 12 is commentTime bottom margin
                contentHeights += contentHeight;
                var card = new CommentCard(
                    message,
                    isPraised,
                    parentName,
                    () => ReportManager.showReportView(this.widget.viewModel.isLoggedIn,
                                                       commentId,
                                                       ReportType.comment, this.widget.actionModel.pushToLogin, this.widget.actionModel.pushToReport
                                                       ),
                    replyCallBack: () => {
                    if (!this.widget.viewModel.isLoggedIn)
                    {
                        this.widget.actionModel.pushToLogin();
                    }
                    else
                    {
                        AnalyticsManager.ClickComment("Article_Comment", this._article.channelId,
                                                      this._article.title, commentId);
                        ActionSheetUtils.showModalActionSheet(new CustomInput(
                                                                  message.author.fullName.isEmpty() ? "" : message.author.fullName,
                                                                  text => {
                            ActionSheetUtils.hiddenModalPopup();
                            this.widget.actionModel.sendComment(this._article.channelId,
                                                                text,
                                                                Snowflake.CreateNonce(),
                                                                commentId
                                                                );
                        })
                                                              );
                    }
                },
                    praiseCallBack: () => {
                    if (!this.widget.viewModel.isLoggedIn)
                    {
                        this.widget.actionModel.pushToLogin();
                    }
                    else
                    {
                        if (isPraised)
                        {
                            this.widget.actionModel.removeLikeComment(message);
                        }
                        else
                        {
                            this.widget.actionModel.likeComment(message);
                        }
                    }
                });
                comments.Add(card);
            }

            float endHeight = 0;

            if (!this._article.hasMore)
            {
                comments.Add(new Container(
                                 height: 52,
                                 alignment: Alignment.center,
                                 child: new Text(
                                     "一 已经全部加载完毕 一",
                                     style: CTextStyle.PRegularBody4,
                                     textAlign: TextAlign.center
                                     )
                                 ));
                endHeight = 52;
            }
            if (titleHeight + contentHeights + endHeight < height)
            {
                return(new List <Widget> {
                    new Container(
                        height: height,
                        child: new Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: comments
                            )
                        )
                });
            }
            return(comments);
        }
Example #8
0
        public override Widget build(BuildContext context)
        {
            this.widget.viewModel.articleDict.TryGetValue(this.widget.viewModel.articleId, out this._article);
            if (this.widget.viewModel.articleDetailLoading && (this._article == null || !this._article.isNotFirst))
            {
                return(new Container(
                           color: CColors.White,
                           child: new CustomSafeArea(
                               child: new Column(
                                   children: new List <Widget> {
                    this._buildNavigationBar(false),
                    new ArticleDetailLoading()
                }
                                   )
                               )
                           ));
            }

            if (this._article == null || this._article.channelId == null)
            {
                return(new Container());
            }

            if (this._article.ownerType == "user")
            {
                if (this._article.userId != null &&
                    this.widget.viewModel.userDict.TryGetValue(this._article.userId, out this._user))
                {
                    this._user = this.widget.viewModel.userDict[this._article.userId];
                }
            }

            if (this._article.ownerType == "team")
            {
                if (this._article.teamId != null &&
                    this.widget.viewModel.teamDict.TryGetValue(this._article.teamId, out this._team))
                {
                    this._team = this.widget.viewModel.teamDict[this._article.teamId];
                }
            }

            if (this._titleHeight == 0f && this._article.title.isNotEmpty())
            {
                this._titleHeight = CTextUtils.CalculateTextHeight(
                    text: this._article.title,
                    textStyle: CTextStyle.H3,
                    MediaQuery.of(context).size.width - 16 * 2, // 16 is horizontal padding
                    null
                    ) + 16;                                     // 16 is top padding
                this.setState(() => { });
            }

            var commentIndex = 0;
            var originItems  = this._article == null ? new List <Widget>() : this._buildItems(context, out commentIndex);

            commentIndex    = this._jumpState == _ArticleJumpToCommentState.active ? commentIndex : 0;
            this._jumpState = _ArticleJumpToCommentState.Inactive;

            var child = new Container(
                color: CColors.Background,
                child: new Column(
                    children: new List <Widget> {
                this._buildNavigationBar(),
                new Expanded(
                    child: new CustomScrollbar(
                        new CenteredRefresher(
                            controller: this._refreshController,
                            enablePullDown: false,
                            enablePullUp: this._article.hasMore,
                            onRefresh: this._onRefresh,
                            onNotification: this._onNotification,
                            children: originItems,
                            centerIndex: commentIndex
                            )
                        )
                    ),
                new ArticleTabBar(this._article.like,
                                  () => {
                    if (!this.widget.viewModel.isLoggedIn)
                    {
                        this.widget.actionModel.pushToLogin();
                    }
                    else
                    {
                        AnalyticsManager.ClickComment("Article", this._article.channelId,
                                                      this._article.title);
                        ActionSheetUtils.showModalActionSheet(new CustomInput(
                                                                  doneCallBack: text => {
                            ActionSheetUtils.hiddenModalPopup();
                            this.widget.actionModel.sendComment(this._article.channelId,
                                                                text,
                                                                Snowflake.CreateNonce(),
                                                                null
                                                                );
                        })
                                                              );
                    }
                },
                                  () => {
                    if (!this.widget.viewModel.isLoggedIn)
                    {
                        this.widget.actionModel.pushToLogin();
                    }
                    else
                    {
                        AnalyticsManager.ClickComment("Article", this._article.channelId,
                                                      this._article.title);
                        ActionSheetUtils.showModalActionSheet(new CustomInput(
                                                                  doneCallBack: text => {
                            ActionSheetUtils.hiddenModalPopup();
                            this.widget.actionModel.sendComment(this._article.channelId,
                                                                text,
                                                                Snowflake.CreateNonce(),
                                                                null
                                                                );
                        })
                                                              );
                    }
                },
                                  () => {
                    if (!this.widget.viewModel.isLoggedIn)
                    {
                        this.widget.actionModel.pushToLogin();
                    }
                    else
                    {
                        if (!this._article.like)
                        {
                            this.widget.actionModel.likeArticle(this._article.id);
                        }
                    }
                },
                                  shareCallback: this.share
                                  )
            }
                    )
                );

            return(new Container(
                       color: CColors.White,
                       child: new CustomSafeArea(
                           child: child
                           )
                       ));
        }
Example #9
0
        IEnumerable <Widget> _buildComments(BuildContext context)
        {
            List <string> channelComments = new List <string>();

            if (this.widget.viewModel.channelMessageList.ContainsKey(key: this._article.channelId))
            {
                channelComments = this.widget.viewModel.channelMessageList[key : this._article.channelId];
            }

            var mediaQuery = MediaQuery.of(context);
            var comments   = new List <Widget> {
                new Container(
                    color: CColors.White,
                    width: mediaQuery.size.width,
                    padding: EdgeInsets.only(16, 16, 16),
                    child: new Text(
                        "评论",
                        style: CTextStyle.H5,
                        textAlign: TextAlign.left
                        )
                    )
            };

            var titleHeight = CTextUtils.CalculateTextHeight(
                "评论",
                CTextStyle.H5,
                mediaQuery.size.width - 16 * 2, // 16 is horizontal padding
                null
                ) + 16;                         // 16 is top padding

            float safeAreaPadding = 0;

            if (Application.platform != RuntimePlatform.Android)
            {
                safeAreaPadding = mediaQuery.padding.vertical;
            }

            var height = mediaQuery.size.height - navBarHeight - 44 - safeAreaPadding;

            if (channelComments.Count == 0)
            {
                var blankView = new Container(
                    height: height - titleHeight,
                    child: new BlankView(
                        "快来写下第一条评论吧",
                        "image/default-comment"
                        )
                    );
                comments.Add(item: blankView);
                return(comments);
            }

            var   messageDict    = this.widget.viewModel.channelMessageDict[key : this._article.channelId];
            float contentHeights = 0;

            foreach (var commentId in channelComments)
            {
                if (!messageDict.ContainsKey(key: commentId))
                {
                    break;
                }

                var  message        = messageDict[key : commentId];
                bool isPraised      = _isPraised(message: message, loginUserId: this.widget.viewModel.loginUserId);
                var  parentName     = "";
                var  parentAuthorId = "";
                if (message.upperMessageId.isNotEmpty())
                {
                    if (messageDict.ContainsKey(key: message.upperMessageId))
                    {
                        var parentMessage = messageDict[key : message.upperMessageId];
                        parentName     = parentMessage.author.fullName;
                        parentAuthorId = parentMessage.author.id;
                    }
                }
                else if (message.parentMessageId.isNotEmpty())
                {
                    if (messageDict.ContainsKey(key: message.parentMessageId))
                    {
                        var parentMessage = messageDict[key : message.parentMessageId];
                        parentName     = parentMessage.author.fullName;
                        parentAuthorId = parentMessage.author.id;
                    }
                }

                var content = MessageUtils.AnalyzeMessage(message.content, message.mentions,
                                                          message.mentionEveryone) + (parentName.isEmpty() ? "" : $"回复@{parentName}");
                var contentHeight = CTextUtils.CalculateTextHeight(
                    content,
                    CTextStyle.PLargeBody,
                    // 16 is horizontal padding, 24 is avatar size, 8 is content left margin to avatar
                    mediaQuery.size.width - 16 * 2 - 24 - 8,
                    null
                    ) + 16 + 24 + 3 + 5 + 22 + 12;
                // 16 is top padding, 24 is avatar size, 3 is content top margin to avatar, 5 is content bottom margin to commentTime
                // 22 is commentTime height, 12 is commentTime bottom margin
                contentHeights += contentHeight;
                var card = new CommentCard(
                    message: message,
                    isPraised: isPraised,
                    parentName: parentName,
                    parentAuthorId: parentAuthorId,
                    () => ReportManager.showReportView(
                        isLoggedIn: this.widget.viewModel.isLoggedIn,
                        reportType: ReportType.comment,
                        () => this.widget.actionModel.pushToLogin(),
                        () => this.widget.actionModel.pushToReport(arg1: commentId, arg2: ReportType.comment)
                        ),
                    replyCallBack: () => this._sendComment(
                        "Article_Comment",
                        message.parentMessageId.isNotEmpty() ? message.parentMessageId : commentId,
                        message.parentMessageId.isNotEmpty() ? commentId : "",
                        message.author.fullName.isEmpty() ? "" : message.author.fullName
                        ),
                    praiseCallBack: () => {
                    if (!this.widget.viewModel.isLoggedIn)
                    {
                        this.widget.actionModel.pushToLogin();
                    }
                    else
                    {
                        if (isPraised)
                        {
                            this.widget.actionModel.removeLikeComment(arg: message);
                        }
                        else
                        {
                            this.widget.actionModel.likeComment(arg: message);
                        }
                    }
                },
                    pushToUserDetail: this.widget.actionModel.pushToUserDetail
                    );
                comments.Add(item: card);
            }

            float endHeight = 0;

            if (!this._article.hasMore)
            {
                comments.Add(new EndView());
                endHeight = 52;
            }

            if (titleHeight + contentHeights + endHeight < height)
            {
                return(new List <Widget> {
                    new Container(
                        height: height,
                        child: new Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: comments
                            )
                        )
                });
            }

            return(comments);
        }
Example #10
0
        public override Widget build(BuildContext context)
        {
            this.widget.viewModel.articleDict.TryGetValue(key: this.widget.viewModel.articleId,
                                                          value: out this._article);
            if (this.widget.viewModel.articleDetailLoading && (this._article == null || !this._article.isNotFirst))
            {
                return(new Container(
                           color: CColors.White,
                           child: new CustomSafeArea(
                               child: new Column(
                                   children: new List <Widget> {
                    this._buildNavigationBar(false),
                    new ArticleDetailLoading()
                }
                                   )
                               )
                           ));
            }

            if (this._article == null || this._article.channelId == null)
            {
                return(new Container(
                           color: CColors.White,
                           child: new CustomSafeArea(
                               child: new Column(
                                   children: new List <Widget> {
                    this._buildNavigationBar(false),
                    new Flexible(
                        child: new BlankView("帖子不存在", "image/default-history")
                        )
                }
                                   )
                               )
                           ));;
            }

            if (this._article.ownerType == "user")
            {
                if (this._article.userId != null &&
                    this.widget.viewModel.userDict.TryGetValue(this._article.userId, out this._user))
                {
                    this._user = this.widget.viewModel.userDict[key : this._article.userId];
                }
            }

            if (this._article.ownerType == "team")
            {
                if (this._article.teamId != null &&
                    this.widget.viewModel.teamDict.TryGetValue(this._article.teamId, out this._team))
                {
                    this._team = this.widget.viewModel.teamDict[key : this._article.teamId];
                }
            }

            if (this._titleHeight == 0f && this._article.title.isNotEmpty())
            {
                this._titleHeight = CTextUtils.CalculateTextHeight(
                    text: this._article.title,
                    textStyle: CTextStyle.H3,
                    MediaQuery.of(context).size.width - 16 * 2, // 16 is horizontal padding
                    null
                    ) + 16;                                     // 16 is top padding
                this.setState(() => { });
            }

            var commentIndex = 0;
            var originItems  = this._article == null ? new List <Widget>() : this._buildItems(context, out commentIndex);

            commentIndex    = this._jumpState == _ArticleJumpToCommentState.active ? commentIndex : 0;
            this._jumpState = _ArticleJumpToCommentState.Inactive;

            Widget contentWidget;

            //happens at the next frame after user presses the "Comment" button
            //we rebuild a CenteredRefresher so that we can calculate out the comment section's position
            if (this._needRebuildWithCachedCommentPosition == false && commentIndex != 0)
            {
                contentWidget = new CenteredRefresher(
                    controller: this._refreshController,
                    enablePullDown: false,
                    enablePullUp: this._article.hasMore,
                    onRefresh: this._onRefresh,
                    onNotification: this._onNotification,
                    children: originItems,
                    centerIndex: commentIndex
                    );
            }
            else
            {
                //happens when the page is updated or (when _needRebuildWithCachedCommentPosition is true) at the next frame after
                //a CenteredRefresher is created and the comment section's position is estimated
                //we use 0 or this estimated position to initiate the SmartRefresher's init scroll offset, respectively
                D.assert(!this._needRebuildWithCachedCommentPosition || this._cachedCommentPosition != null);
                contentWidget = new SmartRefresher(
                    initialOffset: this._needRebuildWithCachedCommentPosition ? this._cachedCommentPosition.Value : 0f,
                    controller: this._refreshController,
                    enablePullDown: false,
                    enablePullUp: this._article.hasMore,
                    onRefresh: this._onRefresh,
                    onNotification: this._onNotification,
                    child: ListView.builder(
                        physics: new AlwaysScrollableScrollPhysics(),
                        itemCount: originItems.Count,
                        itemBuilder: (cxt, index) => originItems[index]
                        ));
                if (this._needRebuildWithCachedCommentPosition)
                {
                    this._needRebuildWithCachedCommentPosition = false;
                    //assume that when we jump to the comment, the title should always be shown as the header
                    //this assumption will fail when an article is shorter than 16 pixels in height (as referred to in _onNotification
                    this._controller.forward();
                    this._isHaveTitle = true;
                }
            }

            var child = new Container(
                color: CColors.Background,
                child: new Column(
                    children: new List <Widget> {
                this._buildNavigationBar(),
                new Expanded(
                    child: new CustomScrollbar(
                        child: contentWidget
                        )
                    ),
                this._buildArticleTabBar()
            }
                    )
                );

            return(new Container(
                       color: CColors.White,
                       child: new CustomSafeArea(
                           child: child
                           )
                       ));
        }
        public override Widget build(BuildContext context)
        {
            this.widget.viewModel.articleDict.TryGetValue(key: this.widget.viewModel.articleId,
                                                          value: out this._article);
            if (this.widget.viewModel.articleDetailLoading && (this._article == null || !this._article.isNotFirst))
            {
                return(new Container(
                           color: CColors.White,
                           child: new CustomSafeArea(
                               child: new Column(
                                   children: new List <Widget> {
                    this._buildNavigationBar(false),
                    new ArticleDetailLoading()
                }
                                   )
                               )
                           ));
            }

            if (this._article == null || this._article.channelId == null)
            {
                return(new Container());
            }

            if (this._article.ownerType == "user")
            {
                if (this._article.userId != null &&
                    this.widget.viewModel.userDict.TryGetValue(this._article.userId, out this._user))
                {
                    this._user = this.widget.viewModel.userDict[key : this._article.userId];
                }
            }

            if (this._article.ownerType == "team")
            {
                if (this._article.teamId != null &&
                    this.widget.viewModel.teamDict.TryGetValue(this._article.teamId, out this._team))
                {
                    this._team = this.widget.viewModel.teamDict[key : this._article.teamId];
                }
            }

            if (this._titleHeight == 0f && this._article.title.isNotEmpty())
            {
                this._titleHeight = CTextUtils.CalculateTextHeight(
                    text: this._article.title,
                    textStyle: CTextStyle.H3,
                    MediaQuery.of(context).size.width - 16 * 2, // 16 is horizontal padding
                    null
                    ) + 16;                                     // 16 is top padding
                this.setState(() => { });
            }

            var commentIndex = 0;
            var originItems  = this._article == null ? new List <Widget>() : this._buildItems(context, out commentIndex);

            commentIndex    = this._jumpState == _ArticleJumpToCommentState.active ? commentIndex : 0;
            this._jumpState = _ArticleJumpToCommentState.Inactive;

            var child = new Container(
                color: CColors.Background,
                child: new Column(
                    children: new List <Widget> {
                this._buildNavigationBar(),
                new Expanded(
                    child: new CustomScrollbar(
                        new CenteredRefresher(
                            controller: this._refreshController,
                            enablePullDown: false,
                            enablePullUp: this._article.hasMore,
                            onRefresh: this._onRefresh,
                            onNotification: this._onNotification,
                            children: originItems,
                            centerIndex: commentIndex
                            )
                        )
                    ),
                this._buildArticleTabBar()
            }
                    )
                );

            return(new Container(
                       color: CColors.White,
                       child: new CustomSafeArea(
                           child: child
                           )
                       ));
        }