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); } }
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); } }