/// <summary> /// Installs a theme from a file, validating the archive in the process. /// Will throw a lot if the archive is invalid. /// </summary> /// <param name="file"></param> /// <returns></returns> public static async Task InstallFromFileAsync(StorageFile file) { var themesDirectory = await ApplicationData.Current.LocalFolder.CreateFolderAsync("Themes", CreationCollisionOption.OpenIfExists); // open the archive using (var fileStream = await file.OpenReadAsync()) using (var archive = await Task.Run(() => new ZipArchive(fileStream.AsStreamForRead(), ZipArchiveMode.Read, true))) { // ensure it has a theme definition and load it Theme theme = null; var themeDefinitionFile = archive.GetEntry("theme.json"); if (themeDefinitionFile == null) { throw new InvalidOperationException("This file does not appear to be a Unicord theme, missing theme.json!"); } using (var reader = new StreamReader(themeDefinitionFile.Open())) theme = JsonConvert.DeserializeObject <Theme>(await reader.ReadToEndAsync()); if (await themesDirectory.TryGetItemAsync(theme.NormalisedName) is StorageFolder directory) { if (await UIUtilities.ShowYesNoDialogAsync("Theme already installed!", "This theme is already installed, do you want to overwrite it?")) { await directory.DeleteAsync(); } else { return; } } foreach (var check in theme.ContractChecks) { if (!ApiInformation.IsApiContractPresent(check.Key, check.Value)) { throw new InvalidOperationException( check.Key == "Windows.Foundation.UniversalApiContract" ? "The version of Windows you're running is not supported by this theme. Sorry!" : "A pre-install check failed! This probably means your device or the version of Windows you're running is not supported by this theme. Sorry!"); } } // if the theme specifies a logo if (theme.DisplayLogo != null) { await LoadDisplayLogo(archive, theme); } var dialog = new InstallThemeDialog(theme); if (await dialog.ShowAsync() == ContentDialogResult.Primary) { var themeRoot = await themesDirectory.CreateFolderAsync(theme.NormalisedName); await Task.Run(() => archive.ExtractToDirectory(themeRoot.Path, true)); } } }
/// <summary> /// Installs a theme from a file, validating the archive in the process. /// Will throw a lot if the archive is invalid. /// </summary> /// <param name="file"></param> /// <returns></returns> public static async Task <Theme> InstallFromArchiveAsync(StorageFile file) { var themesDirectory = await ApplicationData.Current.LocalFolder.CreateFolderAsync(THEME_FOLDER_NAME, CreationCollisionOption.OpenIfExists); var strings = ResourceLoader.GetForViewIndependentUse("ThemesSettingsPage"); // open the archive using (var fileStream = await file.OpenReadAsync()) using (var archive = await Task.Run(() => new ZipArchive(fileStream.AsStreamForRead(), ZipArchiveMode.Read, true))) { // ensure it has a theme definition and load it var theme = await LoadArchiveThemeDefinitionAsync(archive); if (await themesDirectory.TryGetItemAsync(theme.NormalisedName) is StorageFolder directory) { if (await UIUtilities.ShowYesNoDialogAsync(strings.GetString("ThemeAlreadyInstalledTitle"), strings.GetString("ThemeAlreadyInstalledMessage"))) { await directory.DeleteAsync(); } else { return(null); } } // if the theme specifies a logo if (theme.DisplayLogo != null) { await LoadDisplayLogoAsync(archive, theme); } var dialog = new InstallThemeDialog(theme); if (await dialog.ShowAsync() == ContentDialogResult.Primary) { await ValidateAndLoadArchiveAsync(archive, theme, null); var themeRoot = await themesDirectory.CreateFolderAsync(theme.NormalisedName); await Task.Run(() => archive.ExtractToDirectory(themeRoot.Path)); Analytics.TrackEvent("ThemeInstalled", new Dictionary <string, string>() { ["Theme"] = JsonConvert.SerializeObject(theme.Name) }); return(theme); } } return(null); }