private void ValidateAddonGroup(AddonGroup addonGroup) { // add group to subscribed addons string uuid = addonGroup.Uuid; string remoteVersion = addonGroup.RemoteVersion; if (Settings.Instance.SubscribedAddonGroups.ContainsKey(uuid)) { Settings.Instance.SubscribedAddonGroups[uuid] = remoteVersion; } else { Settings.Instance.SubscribedAddonGroups.Add(uuid, remoteVersion); } // update UI Application.Current.Dispatcher.Invoke(new Action(() => { downloadManager = null; addonGroup.StatusText = ""; addonGroup.StatusVisibility = Visibility.Hidden; addonGroup.State = AddonGroupState.Ready; MainWindow.Instance.EnablePlayButton(); foreach (AddonGroup addonGrp in FileIndexer.Instance.AddonGroups) { addonGrp.ButtonIsEnabled = true; } ButtonUpdate.IsEnabled = true; ListViewAddonGroups.Items.Refresh(); })); FileIndexer.Instance.UpdateLocalIndex(); }
private void ButtonDownload_Click(object sender, RoutedEventArgs e) { Button button = (Button)sender; AddonGroup addonGroup = (AddonGroup)button.DataContext; if (downloadManager == null) { // start new download // disable all buttons that should not be pressed while download is running foreach (AddonGroup addonGrp in FileIndexer.Instance.AddonGroups) { if (addonGroup != addonGrp) { addonGrp.ButtonIsEnabled = false; } } ButtonUpdate.IsEnabled = false; ListViewAddonGroups.Items.Refresh(); MainWindow.Instance.PlayUpdateButton.IsEnabled = false; // in case of missing addons decide where to download them to, if all addons already exist locally skip this step FilePath downloadDirectoryForMissingAddons = null; // decide where to download missing addons to switch (Settings.Instance.GetAddonSearchDirectories().Count) { case 0: // there is no addon search directory set, tell user to choose at least one MessageBox.Show(Properties.Resources.MissingAddonSearchDirectoryInfoMessage, "kellerkompanie-sync"); return; case 1: // there is exactly one folder set as search directory, so this one will be download destination for all downloadDirectoryForMissingAddons = Settings.Instance.GetAddonSearchDirectories()[0]; break; default: // there is more than one addon search directory, make user choose to which one he wants to download missing files ChooseDirectoryWindow inputDialog = new(); if (inputDialog.ShowDialog() == true) { downloadDirectoryForMissingAddons = inputDialog.ChosenDirectory; } else { MainWindow.Instance.EnablePlayButton(); foreach (AddonGroup addonGrp in FileIndexer.Instance.AddonGroups) { addonGrp.ButtonIsEnabled = true; } ButtonUpdate.IsEnabled = true; ListViewAddonGroups.Items.Refresh(); return; } break; } if (downloadDirectoryForMissingAddons == null) { throw new InvalidOperationException("the download folder for missing addons is null"); } Dictionary <RemoteAddon, FilePath> webAddonToDownloadDirectoryDict = new(); foreach (RemoteAddon webAddon in addonGroup.RemoteAddons) { if (addonGroup.WebAddonToLocalAddonDict.ContainsKey(webAddon)) { // some addons might already exist, for these download to existing folder LocalAddon existingLocalAddon = addonGroup.WebAddonToLocalAddonDict[webAddon]; string parentFolder = Directory.GetParent(existingLocalAddon.AbsoluteFilepath.OriginalValue).FullName; FilePath addonParentFolder = new(parentFolder); webAddonToDownloadDirectoryDict.Add(webAddon, addonParentFolder); } else { // for all others choose the previously selected folder Debug.Assert(addonGroup.State != AddonGroupState.CompleteButNotSubscribed); webAddonToDownloadDirectoryDict.Add(webAddon, downloadDirectoryForMissingAddons); } } addonGroup.StatusText = Properties.Resources.ProgressDownloading; addonGroup.StatusVisibility = Visibility.Visible; addonGroup.ButtonText = Properties.Resources.Pause; ListViewAddonGroups.Items.Refresh(); BackgroundWorker worker = new(); worker.WorkerReportsProgress = true; worker.DoWork += DownloadWorker_DoWork; DownloadArguments args = new() { AddonGroup = addonGroup, DownloadDirectoryDict = webAddonToDownloadDirectoryDict }; worker.RunWorkerAsync(args); } else if (downloadManager?.State == DownloadState.Paused) { // previous download is about to be resumed downloadManager.StartDownloads(); } else if (downloadManager?.State == DownloadState.Downloading) { // download is currently running, pause it downloadManager.PauseDownloads(); } }
void DownloadWorker_DoWork(object sender, DoWorkEventArgs e) { DownloadArguments args = (DownloadArguments)e.Argument; RemoteIndex remoteIndex = WebAPI.GetIndex(); // determine files to delete AddonGroup addonGroup = args.AddonGroup; foreach (RemoteAddon webAddon in addonGroup.RemoteAddons) { Uuid webAddonUuid = webAddon.Uuid; if (!FileIndexer.Instance.addonUuidToLocalAddonMap.ContainsKey(webAddonUuid)) { continue; } RemoteAddon remAddon = remoteIndex.FilesIndex[webAddon.Uuid]; List <LocalAddon> localAddons = FileIndexer.Instance.addonUuidToLocalAddonMap[webAddonUuid]; foreach (LocalAddon localAddon in localAddons) { List <FilePath> removals = new(); foreach (LocalFileIndex fileIndex in localAddon.Files.Values) { FilePath relativeFilepath = fileIndex.Relative_filepath; if (!remAddon.Files.ContainsKey(relativeFilepath.Replace("\\", "/"))) { FilePath filePath = fileIndex.Absolute_filepath; Log.Debug("deleting " + filePath); removals.Add(filePath); File.Delete(@filePath.Value); } } foreach (FilePath removal in removals) { localAddon.Files.Remove(removal); } } } // determine files to download downloadManager = new DownloadManager(args.AddonGroup); downloadManager.StateChanged += DownloadManager_StateChanged; downloadManager.ProgressChanged += DownloadManager_ProgressChanged; foreach (RemoteAddon webAddon in addonGroup.RemoteAddons) { RemoteAddon remoteAddon = FileIndexer.Instance.RemoteIndex.FilesIndex[webAddon.Uuid]; Uuid uuid = webAddon.Uuid; string name = webAddon.Name; if (!remoteAddon.Uuid.Equals(uuid)) { throw new InvalidOperationException(string.Format("uuid {0} of local addon {1} does not match remote uuid {2} of addon {3}", uuid, name, remoteAddon.Uuid, remoteAddon.Name)); } FilePath destinationFolder = args.DownloadDirectoryDict[webAddon]; if (!FileIndexer.Instance.addonUuidToLocalAddonMap.ContainsKey(uuid)) { // download all foreach (RemoteAddonFile remoteAddonFile in remoteAddon.Files.Values) { FilePath remoteFilePath = remoteAddonFile.Path; FilePath destinationFilePath = FilePath.Combine(destinationFolder, remoteFilePath.Replace("/", "\\")); downloadManager.AddDownload(WebAPI.RepoUrl + "/" + remoteFilePath.OriginalValue, destinationFilePath, remoteAddonFile.Size); } } else { Dictionary <FilePath, LocalFileIndex> relativeFilePathToFileIndexMap = new(); List <LocalAddon> localAddons = FileIndexer.Instance.addonUuidToLocalAddonMap[uuid]; foreach (LocalAddon localAddon in localAddons) { foreach (LocalFileIndex fileIndex in localAddon.Files.Values) { relativeFilePathToFileIndexMap.Add(fileIndex.Relative_filepath, fileIndex); } } // parts of the addon already exist, update existing and download missing foreach (RemoteAddonFile remoteAddonFile in remoteAddon.Files.Values) { FilePath remoteFilePath = remoteAddonFile.Path.Replace("/", "\\"); string remoteHash = remoteAddonFile.Hash; if (relativeFilePathToFileIndexMap.ContainsKey(remoteFilePath)) { LocalFileIndex localFileIndex = relativeFilePathToFileIndexMap[remoteFilePath]; if (!remoteHash.Equals(localFileIndex.Hash)) { FilePath destinationFilepath = FilePath.Combine(destinationFolder, remoteFilePath); downloadManager.AddDownload(WebAPI.RepoUrl + "/" + remoteFilePath.OriginalValue, destinationFilepath, remoteAddonFile.Size); } } else { FilePath destinationFilepath = FilePath.Combine(destinationFolder, remoteFilePath); downloadManager.AddDownload(WebAPI.RepoUrl + "/" + remoteFilePath.OriginalValue, destinationFilepath, remoteAddonFile.Size); } } } } downloadManager.StartDownloads(); }