/// <summary>
 /// Add a story to the container, that doesn't need saving right away, and don't trigger any events.
 /// </summary>
 /// <param name="story"></param>
 private void LoadStory(WdcInteractiveStory newStory)
 {
     lock (_lock)
     {
         _AddStory(newStory, false);
     }
 }
Example #2
0
        private void SetFormState(AddStoryFormState newState)
        {
            _log.Debug($"Setting form state: {newState}.");

            switch (newState)
            {
            case AddStoryFormState.ReadToGetStory:
                EnableSaveButton(false);
                EnableGetStoryButton(true);
                EnableStoryParmInput(true);
                break;

            case AddStoryFormState.GettingStory:
                _story = null;              // Forget the current story
                SetStoryInfo(string.Empty); // Clear the story info
                EnableStoryParmInput(false);
                EnableGetStoryButton(false);
                EnableSaveButton(false);
                break;

            case AddStoryFormState.ReadyToSave:
                EnableStoryParmInput(true);
                EnableGetStoryButton(true);
                EnableSaveButton(true);
                break;
            }

            _formState = newState;
        }
        public void ExportStoryRecentChapters(WdcInteractiveStory story)
        {
            _log.Debug("Exporting story recent chapters");

            var chaptersStorted = story.Chapters.OrderByDescending(c => c.FirstSeen).ToArray();

            var htmlRecentChaptersItems = new StringBuilder();

            foreach (var chapter in chaptersStorted)
            {
                var chapterIsReady = IsChapterReady(chapter);

                htmlRecentChaptersItems.AppendLine(
                    GetTemplate("StoryRecentChaptersItem.html")
                    .Replace("{ChapterName}", chapterIsReady ? chapter.Title : CHAPTER_NOT_EXPORTED_PLACEHOLDER)
                    .Replace("{ChapterSeen}", chapter.FirstSeen.ToString())
                    .Replace("{ChapterPath}", GetPrettyChapterPath(chapter.Path))
                    .Replace("{ChapterLink}", chapterIsReady ? _chapterPathFilename[chapter.Path] : "#")
                    );
            }

            string htmlContent = GetTemplate("StoryRecentChapters.html")
                                 .Replace("{StoryTitle}", story.Name)
                                 .Replace("{RecentChapterItems}", htmlRecentChaptersItems.ToString())
                                 .Replace("{HomeLink}", GetHomepageFileName());

            var html = GetPageTemplate($"{story.Name} - Recent chapters", "Recent chapters", htmlContent);

            var fname = GetRecentChaptersFileName();

            File.WriteAllText(Path.Combine(_outputDir, fname), html);
        }
        private async Task SyncChapter(WdcInteractiveStory story, WdcInteractiveChapter chapter)
        {
            var ct = _ctSource.Token;

            ct.ThrowIfCancellationRequested();

            _log.Debug($"Syncing story '{story.ID}' chapter '{chapter.Path}'");

            // Update the story status
            // TODO

            // If the last synced value is minimum (always update) or chapter refreshing is enabled and this chapter needs a refresh
            if (
                chapter.LastSynced == DateTime.MinValue ||
                (GetSettings().UpdateKnownChapters&& chapter.LastSynced <= DateTime.Now + new TimeSpan(0, 0, GetSettings().SyncChapterIntervalSeconds, 0))
                )
            {
                var remoteChapter = await _wdcReader.GetInteractiveChaper(story.ID, chapter.Path, _wdcClient, ct);

                ct.ThrowIfCancellationRequested();

                // Bring over changes
                chapter.Author            = remoteChapter.Author;
                chapter.Choices           = remoteChapter.Choices;
                chapter.Content           = remoteChapter.Content;
                chapter.IsEnd             = remoteChapter.IsEnd;
                chapter.SourceChoiceTitle = remoteChapter.SourceChoiceTitle;
                chapter.Title             = remoteChapter.Title;

                chapter.LastSynced = DateTime.Now;
            }
        }
        /// <summary>
        /// Show the Edit story form.
        /// </summary>
        /// <param name="story"></param>
        private void ShowEditStoryForm(WdcInteractiveStory story)
        {
            var editStoryForm = _diContainer.GetInstance <EditStoryForm>();

            editStoryForm.SetStory(story);
            editStoryForm.ShowDialog(this);
        }
        public void ExportStoryOutline(WdcInteractiveStory story)
        {
            _log.Debug("Exporting story outline");

            StringBuilder htmlStoryOutline = new StringBuilder();

            foreach (var chapter in story.Chapters)
            {
                var chapterIsReady = IsChapterReady(chapter);
                htmlStoryOutline.AppendLine(
                    GetTemplate("StoryOutlineItem.html")
                    .Replace("{ChapterPathDisplay}", GetPrettyChapterPath(chapter.Path))
                    .Replace("{ChapterPath}", chapter.Path)
                    .Replace("{ChapterName}", chapterIsReady ? chapter.Title : CHAPTER_NOT_EXPORTED_PLACEHOLDER)
                    .Replace("{ChapterLink}", chapterIsReady ? _chapterPathFilename[chapter.Path] : "#")
                    );
            }

            string htmlContent = GetTemplate("StoryOutline.html")
                                 .Replace("{StoryTitle}", story.Name)
                                 .Replace("{OutlineContent}", htmlStoryOutline.ToString())
                                 .Replace("{HomeLink}", GetHomepageFileName());

            var html = GetPageTemplate($"{story.Name} - Chapter outline", "Chapter outline", htmlContent);

            var fname = GetOutlineFileName();

            File.WriteAllText(Path.Combine(_outputDir, fname), html);
        }
 private WdcStoryContainerWrapper GetNewWrapper(WdcInteractiveStory story)
 {
     return(new WdcStoryContainerWrapper()
     {
         Story = story,
         NeedsSave = false
     });
 }
Example #8
0
        public EditStoryForm(IWdcStoryContainer storyContainer)
        {
            _storyContainer = storyContainer;

            _story = new WdcInteractiveStory();

            InitializeComponent();
        }
 public string SerializeStoryToString(WdcInteractiveStory story)
 {
     using (StringWriter sw = new StringWriter())
     {
         _serializer.Serialize(sw, story, _xmlNamespace);
         return(sw.ToString());
     }
 }
        public void SaveStory(WdcInteractiveStory story, string filePath)
        {
            _log.Debug($"Saving story '{story.ID}' to: {filePath}");

            using (var f = File.Open(filePath, FileMode.Create))
            {
                SerializeStory(story, f);
            }
        }
        /// <summary>
        /// Add a story to the container.
        /// </summary>
        /// <param name="newStory"></param>
        public void AddStory(WdcInteractiveStory newStory, bool needsSave)
        {
            lock (_lock)
            {
                _AddStory(newStory, needsSave);
            }

            DoEvent(newStory.ID, WdcStoryContainerEventType.Add);
        }
Example #12
0
        public void XmlSimpleSaveAndLoad()
        {
            var fname = $"{_testStory.ID}-SimpleSaveAndLoad.xml";

            IStoryFileStore fs = new XmlStoryFileStore();

            fs.SaveStory(_testStory, fname);

            WdcInteractiveStory loadedStory = fs.LoadStory(fname);

            AddFileToClean(fname);
        }
        private void _AddStory(WdcInteractiveStory newStory, bool needsSave)
        {
            if (_HasStory(newStory.ID))
            {
                throw new ArgumentException($"A story with the ID of '{newStory.ID}' already exists.");
            }

            var sw = GetNewWrapper(newStory);

            sw.NeedsSave = needsSave;
            _storyCollection.Add(sw);
        }
Example #14
0
        private void SetStoryInfo(WdcInteractiveStory story)
        {
            var sb = new StringBuilder();

            sb.AppendLine($"Title: {story.Name}");
            sb.AppendLine();
            sb.AppendLine("Short description:");
            sb.AppendLine(story.ShortDescription);
            sb.AppendLine();
            sb.AppendLine(story.Description);

            SetStoryInfo(sb.ToString());
        }
Example #15
0
        private void UpdateFormFromStory(WdcInteractiveStory story)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new UpdateFormFromStoryDelegate(UpdateFormFromStory), story);
                return;
            }

            txtStoryName.Text             = _story.Name;
            txtStoryID.Text               = _story.ID;
            txtStoryShortDescription.Text = _story.ShortDescription;
            txtStoryDescription.Text      = _story.Description;
            dtpLastUpdated.Value          = _story.LastUpdatedInfo;
        }
 private string GetPreviousChapterLink(WdcInteractiveStory story, WdcInteractiveChapter chapter)
 {
     if (chapter.Path.Length > 1)
     {
         // E.g. 15524
         var previousChapterPath = _chapterPathFilename[chapter.Path.Substring(0, chapter.Path.Length - 1)];
         return($"This choice: <b>{chapter.SourceChoiceTitle}</b> <a href='{previousChapterPath}'>Go back</a>");
     }
     else
     {
         // E.g. 1
         return($"<a href='{STORY_HOMEPAGE_FILENAME}'>Go back</a>");
     }
 }
        public WdcInteractiveStory GetInteractiveStory(string interactiveID, WdcResponse wdcPayload)
        {
            log.DebugFormat("Getting interactive story: {0}", interactiveID);

            var story = new WdcInteractiveStory();

            // Get interactive story title
            story.ID               = interactiveID;
            story.Url              = wdcPayload.Address;
            story.Name             = GetInteractiveStoryTitle(wdcPayload);
            story.ShortDescription = GetInteractiveStoryShortDescription(wdcPayload);
            story.Description      = GetInteractiveStoryDescription(wdcPayload);
            story.LastUpdatedInfo  = DateTime.Now;

            return(story);
        }
        public void UpdateStory(WdcInteractiveStory newStory)
        {
            lock (_lock)
            {
                var existingStory = _GetStory(newStory.ID);
                if (existingStory == null)
                {
                    throw new ArgumentOutOfRangeException($"A story with the ID of '{newStory.ID}' does not exist.");
                }

                // Copy it over, including all the chapters
                // Remove the old story, add in the replacement
                _RemoveStory(newStory.ID, false);
                _AddStory(newStory, true);
            }

            DoEvent(newStory.ID, WdcStoryContainerEventType.Update);
        }
Example #19
0
        private async void GetStory()
        {
            SetFormState(AddStoryFormState.GettingStory);

            try
            {
                var storyParm = txtStoryParm.Text;

                if (string.IsNullOrEmpty(storyParm))
                {
                    throw new ArgumentNullException("storyParm");
                }

                // If it's a URL, just get the parameter.
                Uri uriOutput;
                if (Uri.TryCreate(storyParm, UriKind.Absolute, out uriOutput))
                {
                    storyParm = uriOutput.Segments.Last(); // Just get the last part, should be the story ID
                }

                _log.Debug($"Getting story info: {storyParm}");

                var storyResult = await _wdcReader.GetInteractiveStory(storyParm, _wdcClient, _ctSourceWdcClient.Token);

                // Made it here, request was successfull
                _story = storyResult;
                SetStoryInfo(storyResult);
            }
            catch (OperationCanceledException ex)
            {
                // Do nothing
            }
            catch (Exception ex)
            {
                // TODO error handling
                _log.Warn("Error while trying to get story", ex);

                ShowError("Error trying to get story", "An error occurred while trying to get the story info.", ex);
            }
            finally
            {
                SetFormState(_story == null ? AddStoryFormState.ReadToGetStory : AddStoryFormState.ReadyToSave);
            }
        }
        public void ExportStoryHomepage(WdcInteractiveStory story)
        {
            _log.Debug("Exporting story homepage");

            string htmlContent = GetTemplate("StoryHomepage.html")
                                 .Replace("{StoryTitle}", story.Name)
                                 //.Replace("{StoryAuthor}", story.Author.Name) // Author isn't currently supported
                                 .Replace("{StoryShortDescription}", story.ShortDescription)
                                 .Replace("{StoryDescription}", story.Description)
                                 .Replace("{FirstPageLink}", _chapterPathFilename["1"])
                                 .Replace("{StoryOutlineLink}", GetOutlineFileName())
                                 .Replace("{RecentChaptersLink}", GetRecentChaptersFileName());

            var html = GetPageTemplate(story.Name, story.Name, htmlContent);

            var fname = GetHomepageFileName();

            File.WriteAllText(Path.Combine(_outputDir, fname), html);
        }
        // Check the list of chapters in WDC. If there are some that we haven't seen before, add placeholder chapters to the story.
        private async Task SyncStoryChapterList(WdcInteractiveStory story)
        {
            var ct = _ctSource.Token;

            ct.ThrowIfCancellationRequested();

            _log.Debug($"Syncing chapter outline for story '{story.ID}'");

            this.SetCurrentStatus(StorySyncWorkerState.WorkingOutline, $"Updating story chapter list: {story.ID}");

            var remoteChapterList = await _wdcReader.GetInteractiveChapterList(story.ID, _wdcClient, ct);

            ct.ThrowIfCancellationRequested();

            foreach (var uri in remoteChapterList)
            {
                var chapterPath = WdcUtil.GetFinalParmFromUrl(uri.ToString()); // Just want the final digits

                // Do we already have that chapter?
                if (!story.Chapters.Exists(c => c.Path == chapterPath))
                {
                    ct.ThrowIfCancellationRequested();

                    _log.InfoFormat("Creating placeholder for new chapter: {0}", chapterPath);

                    var newChapter = new WdcInteractiveChapter()
                    {
                        Path       = chapterPath,
                        LastSynced = DateTime.MinValue,
                        FirstSeen  = DateTime.Now
                    };

                    story.Chapters.Add(newChapter);
                }
            }

            ct.ThrowIfCancellationRequested();

            // Save changes
            story.LastUpdatedChapterOutline = DateTime.Now;
            _storyContainer.UpdateStory(story);
        }
        private string GetChapterChoices(WdcInteractiveStory story, WdcInteractiveChapter chapter)
        {
            if (chapter.IsEnd || chapter.Choices.Count < 1)
            {
                // Is end
                return(GetTemplate("ChapterChoiceEnd.html"));
            }
            else
            {
                // There are choices
                var sbChapterChoices = new StringBuilder();
                foreach (var choice in chapter.Choices)
                {
                    // Does this choice lead to a valid chapter?
                    bool isChoiceValid = story.Chapters.SingleOrDefault(c => c.Path == choice.PathLink) != null;

                    var choiceHtml = String.Empty;

                    // Choice links to a chapter that exists, choice is valid

                    if (isChoiceValid && _chapterPathFilename != null)
                    {
                        choiceHtml = GetTemplate("ChapterChoiceItemValid.html")
                                     .Replace("{ChoicePath}", choice.PathLink)
                                     .Replace("{ChoiceLink}", _chapterPathFilename[choice.PathLink])
                                     .Replace("{ChoiceName}", choice.Name);
                    }
                    else
                    {
                        // Is either an invalid choice, or the path / filename lookup is missing (could be for a once-off chapter export)
                        choiceHtml = GetTemplate("ChapterChoiceItemInvalid.html")
                                     .Replace("{ChoiceName}", choice.Name);
                    }

                    sbChapterChoices.AppendLine(choiceHtml);
                }

                return(GetTemplate("ChapterChoiceList.html")
                       .Replace("{ChoiceList}", sbChapterChoices.ToString()));
            }
        }
        public void ExportStoryChapter(WdcInteractiveStory story, WdcInteractiveChapter chapter, string filename)
        {
            _log.DebugFormat("Exporting chapter: {0}", chapter.Path);

            var chapterIsReady = IsChapterReady(chapter);
            var htmlContent    = GetTemplate("Chapter.html")
                                 .Replace("{AuthorName}", chapter.Author.Name)
                                 .Replace("{ChapterPath}", chapter.Path)
                                 .Replace("{ChapterPathDisplay}", GetPrettyChapterPath(chapter.Path))
                                 .Replace("{SourceChapterChunk}", GetPreviousChapterLink(story, chapter))
                                 .Replace("{ChapterChoices}", GetChapterChoices(story, chapter))
                                 .Replace("{ChapterContent}", chapter.Content)
                                 .Replace("{ChapterTitle", chapter.Title)
                                 .Replace("{HomeLink}", GetHomepageFileName());

            var html = GetPageTemplate($"{story.Name} - {chapter.Title}", chapter.Title, htmlContent);

            // TODO: Fix the "Go back" link


            File.WriteAllText(Path.Combine(_outputDir, filename), html);
        }
        public void ExportStory(WdcInteractiveStory story)
        {
            _log.InfoFormat("Exporting story '{0}' to path: {1}", story.ID, _outputDir);

            DoProgressUpdate("Getting ready to export", 0, 0);

            // Create the missing directories, if need be
            Directory.CreateDirectory(_outputDir);

            // Create the chapter path / chapter filename map.
            // Not sure, but one day these might not be so simple, like if we hit the filename length limit.
            _chapterPathFilename = new Dictionary <string, string>();
            foreach (var chapter in story.Chapters)
            {
                _chapterPathFilename.Add(chapter.Path, GetChapterFileName(chapter));
            }

            DoProgressUpdate("Exporting story homepage", 0, _chapterPathFilename.Count);
            ExportStoryHomepage(story);

            DoProgressUpdate("Exporting story outline", 0, _progressMax);
            ExportStoryOutline(story);

            DoProgressUpdate("Exporting recent chapters", 0, _progressMax);
            ExportStoryRecentChapters(story);

            //foreach (var chapter in story.Chapters)
            for (var i = 0; i < story.Chapters.Count; i++)
            {
                var chapter        = story.Chapters[i];
                var chapterIsReady = IsChapterReady(chapter);
                DoProgressUpdate($"Exporting chapter {chapter.Path}", i, _progressMax);
                if (chapterIsReady)
                {
                    ExportStoryChapter(story, chapter, _chapterPathFilename[chapter.Path]);
                }
            }
        }
        // WARNING: is not thread safe
        private void _AddStoryRow(WdcInteractiveStory story)
        {
            var newRow = new DataGridViewRow();

            newRow.Tag = story.ID;
            newRow.Cells.Add(new DataGridViewTextBoxCell()
            {
                Value = null
            });
            newRow.Cells.Add(new DataGridViewTextBoxCell()
            {
                Value = null
            });
            newRow.Cells.Add(new DataGridViewTextBoxCell()
            {
                Value = story.Name, ToolTipText = story.Name
            });

            dgvStories.Rows.Add(newRow);

            // Update row from sync status
            UpdateStoryListRow(newRow, _syncWorker.GetStoryStatus(story.ID));
        }
        // Update the story details
        private async Task SyncStoryInfo(WdcInteractiveStory story)
        {
            var ct = _ctSource.Token;

            ct.ThrowIfCancellationRequested();

            _log.InfoFormat("Syncing story info: {0}", story.ID);

            var remoteStory = await _wdcReader.GetInteractiveStory(story.ID, _wdcClient, _ctSource.Token);

            ct.ThrowIfCancellationRequested();

            // Bring over changes
            story.Author           = remoteStory.Author;
            story.Name             = remoteStory.Name;
            story.ShortDescription = remoteStory.ShortDescription;
            story.Description      = remoteStory.Description;
            story.LastUpdatedInfo  = DateTime.Now;

            // Save changes
            ct.ThrowIfCancellationRequested();
            _storyContainer.UpdateStory(story);
        }
        private async Task SyncStory(WdcInteractiveStory story)
        {
            _log.Debug($"Syncing story '{story.ID}'");
            var ct = _ctSource.Token;

            ct.ThrowIfCancellationRequested();

            // Update story's status, mark as in progress
            //SetStoryStatusState(story.ID, StorySyncWorkerStoryState.Working);
            SetCurrentStatus(StorySyncWorkerState.WorkingStory, $"Working on story: {story.ID}", story.ID);
            //SetStoryStatusProgress(story.ID, 0, 0);

            // Catch specific exceptions
            try
            {
                if (CheckIfStoryInfoNeedsSync(story))
                {
                    SetStoryStatusState(story.ID, StorySyncWorkerStoryState.Working);
                    SetCurrentStatus(StorySyncWorkerState.WorkingStory, $"Updating story info: {story.ID}", story.ID);
                    await SyncStoryInfo(story);
                }
                else
                {
                    _log.Debug("Story info does not need updating");
                }

                if (CheckIfChapterOutlineNeedsSync(story))
                {
                    SetStoryStatusState(story.ID, StorySyncWorkerStoryState.Working);
                    SetCurrentStatus(StorySyncWorkerState.WorkingOutline, $"Updating chapter outline: {story.ID}", story.ID);
                    await SyncStoryChapterList(story);
                }
                else
                {
                    _log.Debug("Story chapter outline does not need updating");
                }

                ct.ThrowIfCancellationRequested();

                // Build a list of chapters that need updating
                SetCurrentStatus(StorySyncWorkerState.WorkingStory, $"Checking for any chapters that need syncing: {story.ID}", story.ID);
                List <WdcInteractiveChapter> chaptersToSync = new List <WdcInteractiveChapter>();
                foreach (var chapter in story.Chapters)
                {
                    if (CheckIfChapterNeedsSync(chapter))
                    {
                        chaptersToSync.Add(chapter);
                    }
                }

                ct.ThrowIfCancellationRequested();

                // If there are no chapters to update, set progress to maximum
                if (chaptersToSync.Count < 1)
                {
                    SetStoryStatusProgress(story.ID, story.Chapters.Count, story.Chapters.Count);
                    _log.Debug("No chapters need updating");
                }
                else
                {
                    SetStoryStatusState(story.ID, StorySyncWorkerStoryState.Working); // About to start working
                }

                // Start syncing the chapters
                for (var i = 0; i < chaptersToSync.Count; i++)
                {
                    ct.ThrowIfCancellationRequested();

                    var chapter = chaptersToSync[i];

                    // Update status

                    SetCurrentStatus(StorySyncWorkerState.WorkingChapter, $"Updating story chapter: {story.ID}, {chapter.Path}", story.ID);
                    SetStoryStatusProgress(story.ID, story.Chapters.Count - (chaptersToSync.Count - i), story.Chapters.Count);

                    // Sync the chapter
                    await SyncChapter(story, chapter);

                    // Save changes after updating the chapter
                    // TODO: is this too much? updating the entire sory when just a single chapter changes? Will it cause issues with stuff listening for container change events?
                    _storyContainer.UpdateStory(story);
                }

                // Done sync for this story. Mark story status as idle
                SetStoryStatusState(story.ID, StorySyncWorkerStoryState.Idle);
                SetCurrentStatus(StorySyncWorkerState.Idle, $"Story update complete: {story.ID}", string.Empty);
            } // End of try block
            catch (InteractivesTemporarilyUnavailableException)
            {
                _log.Info($"Encountered ITU message for story: {story.ID}");
                SetStoryStatusState(story.ID, StorySyncWorkerStoryState.WaitingItu);
            }
            catch (WritingClientHtmlParseException ex)
            {
                _log.Warn("Error trying to parse HTML from Writing.com", ex);

                // Dump the HTML
                var sbDump = new StringBuilder();
                sbDump.AppendLine($"<!-- Exception: {ex.Message} -->");
                sbDump.AppendLine($"<!-- URL: {ex.Address} -->");
                sbDump.AppendLine(ex.HtmlResult);
                var dumpFilePath = _fileDumper.DumpFile("HtmlParseError", sbDump.ToString());

                // Show an error message
                var sbExMsg = new StringBuilder();
                sbExMsg.AppendLine("A HTML parse exception was encountered with the below details:");
                sbExMsg.AppendLine("======================");
                sbExMsg.AppendLine(ex.Message);
                sbExMsg.AppendLine("======================");
                sbExMsg.AppendLine("The HTML response has been dumped to this location:");
                sbExMsg.AppendLine(dumpFilePath);

                _gui.ShowMessageBox("HTML parse exception", sbExMsg.ToString(), GuiMessageBoxIcon.Error);

                // Set the story's status to Error, so it doesn't keep trying to sync and cause more errors
                SetStoryStatusError(story.ID, ex.Message);
            }
            catch (Exception ex)
            {
                _log.Warn($"Encountered unhandled exception while syncing story '{story.ID}'", ex);

                var sb = new StringBuilder();
                sb.AppendLine(ex.GetType().Name);
                sb.AppendLine(ex.Message);

                SetStoryStatusError(story.ID, sb.ToString());

                _gui.ShowExceptionDialog(ex);
            }

            SetCurrentStatus(StorySyncWorkerState.Idle, $"Story update complete: {story.ID}", string.Empty);
        }
 public bool CheckIfChapterOutlineNeedsSync(WdcInteractiveStory story)
 {
     return(story.LastUpdatedChapterOutline + new TimeSpan(0, 0, GetSettings().SyncChapterOutlineIntervalSeconds, 0) < DateTime.Now);
 }
 public bool CheckIfStoryInfoNeedsSync(WdcInteractiveStory story)
 {
     return(story.LastUpdatedInfo + new TimeSpan(0, 0, GetSettings().SyncStoryIntervalSeconds, 0) < DateTime.Now);
 }
Example #30
0
 public void SetStory(WdcInteractiveStory newStory)
 {
     _story      = newStory;
     _isNewStory = false;
     UpdateFormFromStory(newStory);
 }