예제 #1
0
        public static ContentPanelSource CreateFromUrl(string url)
        {
            ContentPanelSource source = new ContentPanelSource();

            source.Id  = c_genericIdBase + DateTime.Now.Ticks;
            source.Url = url;
            return(source);
        }
        /// <summary>
        /// This is called by every piece of content when it is done loading or errors out.
        /// </summary>
        /// <param name="sourceId"></param>
        public async void OnContentLoadComplete(string sourceId)
        {
            // Delay a little bit since this might kick off a background load
            // and it isn't super important.
            await Task.Delay(100);

            bool isSourceVisible          = false;
            ContentPanelSource nextSource = null;

            lock (m_currentPanelList)
            {
                // Check if we are waiting on us
                if (m_currentLoadingContent != null && m_currentLoadingContent.Equals(sourceId))
                {
                    if (m_delayLoadQueue.Count == 0)
                    {
                        // If the queue is empty set current to null and
                        // return.
                        m_currentLoadingContent = null;
                        return;
                    }
                    else
                    {
                        // Otherwise, grab the next element
                        nextSource = m_delayLoadQueue.First();
                        m_delayLoadQueue.RemoveAt(0);

                        // Get if the source is visible.
                        if (m_currentPanelList.ContainsKey(nextSource.Id))
                        {
                            isSourceVisible = m_currentPanelList[nextSource.Id].IsVisible;
                        }

                        // Set it loading
                        m_currentLoadingContent = nextSource.Id;
                    }
                }
                else
                {
                    // Not waiting on us. Get out of here.
                    return;
                }
            }

            // And out of lock start loading.
            if (nextSource != null)
            {
                BeginLoadContent(nextSource, isSourceVisible);
            }
        }
예제 #3
0
        public static ContentPanelSource CreateFromPost(FlipViewPostContext context, Post post)
        {
            ContentPanelSource source = new ContentPanelSource();

            source.Id        = post.Id;
            source.Url       = post.Url;
            source.SelfText  = post.Selftext;
            source.Subreddit = post.Subreddit;
            source.IsNSFW    = post.IsOver18;
            source.IsSelf    = post.IsSelf;

            source.post = post;

            source.context = context;

            return(source);
        }
        /// <summary>
        /// Adds the content to the list of content that is allowed. If someone requested or request this
        /// content they will get a control.
        /// </summary>
        /// <param name="source"></param>
        public void AddAllowedContent(ContentPanelSource source, string groupId = "default", bool delayLoad = false)
        {
            bool isSourceVisible = false;

            // First add an entry that we are making the control.
            lock (m_currentPanelList)
            {
                ContentListElement element;
                // Check to see if it already exists.
                if (m_currentPanelList.ContainsKey(source.Id))
                {
                    element = m_currentPanelList[source.Id];
                    if (element.State != ContentState.NotAllowed)
                    {
                        // We already have this element and it is already loading.
                        // just leave.
                        return;
                    }
                    element.State  = ContentState.PendingCreation;
                    element.Source = source;
                    element.Group  = groupId;

                    // If we have a host tell them we are starting to load their
                    // content (even though it might be delay loaded). This is safe
                    // to call under lock because it will async to the UI thread.
                    if (element.Host != null)
                    {
                        FireOnContentPreloading(element.Host);
                    }
                }
                else
                {
                    // No one is listening, just make the object.
                    element = new ContentListElement()
                    {
                        State  = ContentState.PendingCreation,
                        Group  = groupId,
                        Source = source
                    };
                    m_currentPanelList.Add(source.Id, element);
                }

                // Set if we are visible or not
                isSourceVisible = element.IsVisible;

                // Check if we are delay load.
                if (delayLoad)
                {
                    // If so, check if there is content loading.
                    if (String.IsNullOrWhiteSpace(m_currentLoadingContent))
                    {
                        // If not then load us now.
                        m_currentLoadingContent = source.Id;
                    }
                    else
                    {
                        // Otherwise add use to the list and return
                        // #todo add a timeout to the waiting.
                        m_delayLoadQueue.Add(source);
                        return;
                    }
                }
                else
                {
                    // If we are not delay loading set us to be the current content
                    // we are waiting on. Even if there is someone else, people should
                    // wait on this content.
                    m_currentLoadingContent = source.Id;
                }
            }

            // If we got here we need to load some content!
            BeginLoadContent(source, isSourceVisible);
        }
        /// <summary>
        /// When fired the source given should fall back to a web
        /// browser instead of a complex control.
        /// </summary>
        public async void FallbackToWebrowser(ContentPanelSource source)
        {
            IContentPanelHost hostToReport = null;
            IContentPanelBase panelToKill  = null;

            // Fire on load complete so if someone else was waiting on us they will
            // move on.
            OnContentLoadComplete(source.Id);

            // Lock
            lock (m_currentPanelList)
            {
                // Make sure we have it.
                if (m_currentPanelList.ContainsKey(source.Id))
                {
                    // Grab the panel to kill and the host to tell.
                    ContentListElement element = m_currentPanelList[source.Id];
                    hostToReport = element.Host;
                    panelToKill  = element.PanelBase;

                    // Null the post and update our state
                    element.PanelBase = null;
                    element.State     = ContentState.Unloaded;
                }
                else
                {
                    return;
                }
            }

            // Remove the panel
            if (hostToReport != null && panelToKill != null)
            {
                await FireOnRemovePanel(hostToReport, panelToKill);
            }

            // Kill the panel
            if (panelToKill != null)
            {
                await FireOnDestroyContent(panelToKill);

                panelToKill = null;
            }

            ContentPanelSource sourceToCreate = null;
            bool isVisible = false;

            // Now lock again
            lock (m_currentPanelList)
            {
                // Make sure we still have it.
                if (m_currentPanelList.ContainsKey(source.Id))
                {
                    ContentListElement element = m_currentPanelList[source.Id];
                    if (element.State == ContentState.Unloaded)
                    {
                        // Grab the element again and set the new state.
                        isVisible = element.IsVisible;
                        element.Source.ForceWeb = true;
                        sourceToCreate          = element.Source;
                        element.State           = ContentState.PendingCreation;
                    }
                    else
                    {
                        // if we are not in the same state get out of here.
                        return;
                    }
                }
                else
                {
                    return;
                }
            }

            if (sourceToCreate != null)
            {
                BeginLoadContent(sourceToCreate, isVisible);
            }
        }
        /// <summary>
        /// This will actually do the loading of content. This starts the load but
        /// the load isn't actually done until the app fires the loading function above.
        /// </summary>
        /// <param name="source"></param>
        private void BeginLoadContent(ContentPanelSource source, bool isVisible)
        {
            // Next make the control, spin this off to keep the UI thread going.
            Task.Run(async() =>
            {
                // Create a new base and panel.
                ContentPanelBase panelBase = new ContentPanelBase();
                bool panelLoaded           = await panelBase.CreateContentPanel(source, CanLoadLaregePanel(isVisible));

                bool destoryPanel = true;
                IContentPanelHost hostToGivePanel      = null;
                IContentPanelHost hostToInformUnlaoded = null;

                // Update the list with the control
                lock (m_currentPanelList)
                {
                    // Make sure it is still there.
                    if (m_currentPanelList.ContainsKey(source.Id))
                    {
                        ContentListElement element = m_currentPanelList[source.Id];

                        // Make sure we still have a good state.
                        if (element.State == ContentState.PendingCreation)
                        {
                            // Make sure the panel loaded
                            if (panelLoaded)
                            {
                                // Set the panel and state, if we have a host grab it.
                                destoryPanel      = false;
                                element.PanelBase = panelBase;
                                element.State     = ContentState.Created;
                                hostToGivePanel   = element.Host;
                            }
                            else
                            {
                                // If we didn't load it was probably due to low memory.
                                // Set our state to unloaded and tell the host.
                                element.State        = ContentState.Unloaded;
                                hostToInformUnlaoded = element.Host;
                                destoryPanel         = true;
                            }
                        }
                    }
                }

                // If the entry is now gone or whatever, destroy the post.
                if (destoryPanel)
                {
                    await FireOnDestroyContent(panelBase);
                }
                else
                {
                    // If we have a host inform them the panel is now ready.
                    if (hostToGivePanel != null)
                    {
                        FireOnPanelAvailable(hostToGivePanel, panelBase);
                    }
                }

                // If we have a host to tell that we unloaded the panel tell them.
                if (hostToInformUnlaoded != null)
                {
                    FireOnPanelUnloaded(hostToInformUnlaoded);
                }
            });
        }
        /// <summary>
        /// Called when a panel changes visibility.
        /// </summary>
        /// <param name="sourcdId"></param>
        public void OnPanelVisibliltyChanged(string sourceId, bool isVisible)
        {
            ContentPanelSource loadNowSource = null;

            lock (m_currentPanelList)
            {
                // See if the panel exists.
                if (m_currentPanelList.ContainsKey(sourceId))
                {
                    // Get the element
                    ContentListElement element = m_currentPanelList[sourceId];

                    // Set the new visibility
                    element.IsVisible = isVisible;

                    // If we aren't visible get out of here now.
                    if (!isVisible)
                    {
                        return;
                    }

                    // If we are unloaded start loading right now.
                    if (element.State == ContentState.Unloaded)
                    {
                        // Grab the source
                        loadNowSource = element.Source;

                        // Set our state to pending.
                        element.State = ContentState.PendingCreation;

                        // Make the delay loading id this so everyone will wait on us.
                        m_currentLoadingContent = loadNowSource.Id;
                    }
                    // If we are pending make sure we aren't being delayed.
                    else if (element.State == ContentState.PendingCreation)
                    {
                        // See if this post is in the delay load post list.
                        foreach (ContentPanelSource source in m_delayLoadQueue)
                        {
                            if (source.Id.Equals(sourceId))
                            {
                                loadNowSource = source;
                                break;
                            }
                        }

                        // If we found the element clean it out of the queue
                        if (loadNowSource != null)
                        {
                            // Remove us from it and start loading now!
                            m_delayLoadQueue.Remove(loadNowSource);

                            // We want to load this now. No matter if we were currently waiting on someone or not
                            // all delay loaded post should wait on this one.
                            m_currentLoadingContent = loadNowSource.Id;
                        }
                    }
                }
            }

            // Now that we are out of lock load the source if we have
            // one to load.
            if (loadNowSource != null)
            {
                BeginLoadContent(loadNowSource, true);
            }
        }