Skip to content
Snippets Groups Projects
Select Git revision
  • e72856b765aa80f5cc7ce1a5f40e20a3fa89c8a0
  • master default protected
  • release/201811
  • release/201812
  • release/201901
  • release/201902
  • release/201903
  • release/201904
  • release/201905
  • release/201906
  • release/201908
  • release/201912
  • release/202001
  • release/202005
  • release/windows-test/201910
  • release/201808
  • wip/smartlist_refacto
  • wip/patches_poly_2017/JimmyHamel/MathieuGirouxHuppe
18 results

SmartPanel.xaml.cpp

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    TextBlockExtension.cpp 9.62 KiB
    /**************************************************************************
    * Copyright (C) 2016 by Savoir-faire Linux                                *
    * Author: Traczyk Andreas <traczyk.andreas@savoirfairelinux.com>          *
    *                                                                         *
    * This program is free software; you can redistribute it and/or modify    *
    * it under the terms of the GNU General Public License as published by    *
    * the Free Software Foundation; either version 3 of the License, or       *
    * (at your option) any later version.                                     *
    *                                                                         *
    * This program is distributed in the hope that it will be useful,         *
    * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
    * GNU General Public License for more details.                            *
    *                                                                         *
    * You should have received a copy of the GNU General Public License       *
    * along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
    **************************************************************************/
    
    #include "pch.h"
    #include "TextBlockExtension.h"
    #include "HttpUtils.h"
    
    using namespace RingClientUWP;
    using namespace UserAndCustomControls;
    
    using namespace Platform;
    using namespace Windows::Foundation;
    using namespace Windows::Foundation::Collections;
    using namespace Windows::UI::Xaml;
    using namespace Windows::UI::Xaml::Controls;
    using namespace Windows::UI::Xaml::Controls::Primitives;
    using namespace Windows::UI::Xaml::Data;
    using namespace Windows::UI::Xaml::Input;
    using namespace Windows::UI::Xaml::Media;
    using namespace Windows::UI::Xaml::Media::Imaging;
    using namespace Windows::UI::Xaml::Navigation;
    using namespace Windows::UI::Xaml::Interop;
    using namespace Windows::UI::Xaml::Documents;
    using namespace Windows::UI::Core;
    
    TextBlockExtension::TextBlockExtension()
    {}
    
    void
    embeddedLoadCompleted(Object^ sender, NavigationEventArgs^ e)
    {
        RingD::instance->raiseMessageDataLoaded();
    }
    
    void
    imageLoadCompleted(Object^ sender, RoutedEventArgs^ e)
    {
        RingD::instance->raiseMessageDataLoaded();
    }
    
    void
    appendUrlToParagraph(Uri^ uri, Run^ run, Paragraph^ paragraph, bool& frameAdded, String^ str)
    {
        Hyperlink^ link = ref new Hyperlink();
        link->NavigateUri = uri;
        link->Foreground = ref new Windows::UI::Xaml::Media::SolidColorBrush(Windows::UI::Colors::DarkBlue);
        run->Text = str;
        link->Inlines->Append(run);
        if (frameAdded) {
            paragraph->Inlines->Append(ref new LineBreak());
            frameAdded = false;
        }
        paragraph->Inlines->Append(link);
    }
    
    DependencyProperty^ TextBlockExtension::FormattedTextProperty =
    DependencyProperty::Register("FormattedText", String::typeid, TextBlockExtension::typeid,
        ref new PropertyMetadata(nullptr,
            ref new PropertyChangedCallback([](DependencyObject^ sender, DependencyPropertyChangedEventArgs^ e)
    {
        auto text = Utils::toString(static_cast<String^>(e->NewValue));
        auto rtextBlock = static_cast<RichTextBlock^>(sender);
        rtextBlock->Blocks->Clear();
        auto paragraph = ref new Paragraph();
        if (paragraph != nullptr) {
            static auto regex_opts = std::regex_constants::icase;
            const static std::regex abs_url_regex("((((https?):\/\/))[^\ ]+)", regex_opts);
            const static std::regex url_regex("((((https?):\/\/)|www)[^\ ]+)", regex_opts);
            const static std::regex youtube_regex("(https?\:\/\/)?(www\.)?(youtube\.com|youtu\.?be)([^\=]+)=([^\ ]+)", regex_opts);
            const static std::regex image_regex("[^\ ]+\.(gif|jpg|jpeg|png)", regex_opts);
            const static std::regex word_regex("([^\ ]+)", regex_opts);
    
            // emojis
            const static std::regex emoji_smile("(^|\s):-?\\)(?!\S)|:smile", regex_opts);
            const static std::regex emoji_wink("(^|\s);-?\\)(?!\S)|:wink", regex_opts);
            const static std::regex emoji_grin("(^|\s):-?D(?!\S)|:grin", regex_opts);
            const static std::regex emoji_meh("(^|\s):-?\\)(?!\S)|:meh", regex_opts);
            const static std::regex emoji_sad("(^|\s):-?\\((?!\S)|:sad", regex_opts);
            const static std::regex emoji_crazy("(^|\s);-?P(?!\S)", regex_opts);
            const static std::regex emoji_tongue("(^|\s):-?P(?!\S)", regex_opts);
            const static std::regex emoji_hmm("(^|\s):-?\\/(?!\S)");
            const static std::regex emoji_rofl(":rofl", regex_opts);
            const static std::regex emoji_heart("(^|\s)<3(?!\S)|:heart", regex_opts);
    
            std::sregex_iterator next(text.begin(), text.end(), word_regex);
            std::sregex_iterator end;
            unsigned elementCount = 0;
            bool frameAdded = false;
            while (next != end) {
                Run^ run = ref new Run();
                Run^ postSpace = ref new Run();
                postSpace->Text = " ";
                std::smatch match = *next;
                auto str = Utils::toPlatformString(match.str());
                if (std::regex_match(match.str(), url_regex)) {
                    // it's a url so make it absolute if it's not already
                    if (!std::regex_match(match.str(), abs_url_regex))
                        str = "http://" + str;
                    auto uri = ref new Uri(str);
    
                    // youtube embed
                    std::smatch groups;
                    std::string sub(match.str());
                    if (std::regex_search(sub, groups, youtube_regex)) {
                        if (Utils::hasInternet()) {
                            WebView^ webview = ref new WebView();
                            webview->Width = 372;
                            webview->Height = 208;
                            auto videoId = Utils::toPlatformString(groups[5].str());
                            String^ bodyStr = "<style>iframe,html,body{border:0px;margin:0px;padding:0px;overflow-y:hidden;}</style>";
                            auto iframeStr = "<iframe width='372' height='210' src='https://www.youtube.com/embed/" +
                                videoId + "' frameborder='0'></iframe>";
                            webview->Margin = Windows::UI::Xaml::Thickness(2.0, 6.0, 4.0, 4.0);
                            webview->NavigateToString(bodyStr + iframeStr);
                            webview->LoadCompleted += ref new LoadCompletedEventHandler(&embeddedLoadCompleted);
                            InlineUIContainer^ iuc = ref new InlineUIContainer();
                            iuc->Child = webview;
                            if (elementCount > 0)
                                paragraph->Inlines->Append(ref new LineBreak());
                            paragraph->Inlines->Append(iuc);
                            frameAdded = true;
                        }
                        else {
                            appendUrlToParagraph(uri, run, paragraph, frameAdded, str);
                        }
                    }
                    // image
                    else if (std::regex_match(match.str(), image_regex)) {
                        if (Utils::hasInternet()) {
                            Image^ image = ref new Image();
                            image->Source = ref new BitmapImage(uri);
                            image->MaxWidth = 300;
                            image->Margin = Windows::UI::Xaml::Thickness(2.0, 6.0, 4.0, 4.0);
                            image->Loaded += ref new RoutedEventHandler(&imageLoadCompleted);
                            InlineUIContainer^ iuc = ref new InlineUIContainer();
                            iuc->Child = image;
                            if (elementCount > 0)
                                paragraph->Inlines->Append(ref new LineBreak());
                            paragraph->Inlines->Append(iuc);
                            frameAdded = true;
                        }
                        else {
                            appendUrlToParagraph(uri, run, paragraph, frameAdded, str);
                        }
                    }
                    else {
                        appendUrlToParagraph(uri, run, paragraph, frameAdded, str);
                    }
                }
                // text chunk
                else {
                    // convert text emoji representations to unicode
                    auto ansiEmojiString = std::regex_replace(match.str(), emoji_smile, "🙂");
                    ansiEmojiString = std::regex_replace(ansiEmojiString, emoji_wink, "😉");
                    ansiEmojiString = std::regex_replace(ansiEmojiString, emoji_grin, "😁");
                    ansiEmojiString = std::regex_replace(ansiEmojiString, emoji_meh, "😐");
                    ansiEmojiString = std::regex_replace(ansiEmojiString, emoji_sad, "☹");
                    ansiEmojiString = std::regex_replace(ansiEmojiString, emoji_crazy, "😜");
                    ansiEmojiString = std::regex_replace(ansiEmojiString, emoji_tongue, "😛");
                    ansiEmojiString = std::regex_replace(ansiEmojiString, emoji_hmm, "🤔");
                    ansiEmojiString = std::regex_replace(ansiEmojiString, emoji_rofl, "🤣");
                    ansiEmojiString = std::regex_replace(ansiEmojiString, emoji_heart, "❤");
                    run->Text = Utils::toPlatformString(ansiEmojiString);
                    if (frameAdded) {
                        paragraph->Inlines->Append(ref new LineBreak());
                        frameAdded = false;
                    }
                    paragraph->Inlines->Append(run);
                }
                // add space after everything
                paragraph->Inlines->Append(postSpace);
                elementCount++;
                next++;
            }
            rtextBlock->Blocks->Append(paragraph);
        }
    })));