/// <summary> /// Gets image identifier for given weather icon description /// </summary> /// <param name="iconDescription">weather icon description</param> /// <returns>image identifier string</returns> private static async Task <string> GetImageIdentifierAsync(WeatherIconDescription iconDescription) { string identifier = iconDescription.Type + "|"; switch (iconDescription.Type) { case WeatherIconDescription.IconType.IconLink: identifier += await GetFaviconFromLinkAsync(iconDescription.WebLink); break; case WeatherIconDescription.IconType.IconApp: identifier += iconDescription.WebLink; break; case WeatherIconDescription.IconType.IconPlaceholder: identifier += "placeholder"; break; default: break; } return(identifier); }
/// <summary> /// (Re-)opens web link from weather icon description /// </summary> /// <param name="iconDescription">weather icon description to open</param> private void OpenWebLink(WeatherIconDescription iconDescription) { this.Title = iconDescription.Name; var urlSource = new UrlWebViewSource { Url = iconDescription.WebLink }; if (this.Content == null) { var webView = new WebView { Source = urlSource, VerticalOptions = LayoutOptions.FillAndExpand, HorizontalOptions = LayoutOptions.FillAndExpand }; webView.AutomationId = "WeatherDetailsWebView"; this.Content = webView; } else { var webView = this.Content as WebView; webView.Source = urlSource; } }
/// <summary> /// Adds a new weather icon description to the weather dashboard icon list /// </summary> /// <param name="weatherIconDescriptionToAdd">weather icon description to add</param> /// <returns>task to wait on</returns> public async Task Add(WeatherIconDescription weatherIconDescriptionToAdd) { await this.connection.InsertAsync( new WeatherDashboardIconEntry { WeatherIconDescriptionId = await this.IdFromDescription(weatherIconDescriptionToAdd) }); }
/// <summary> /// Creates new weather details page /// </summary> /// <param name="iconDescription">weather icon description to open</param> public WeatherDetailsPage(WeatherIconDescription iconDescription) { this.OpenWebLink(iconDescription); this.AddRefreshToolbarButton(); this.AddWeatherForecastToolbarButton(); this.AddCurrentWeatherToolbarButton(); this.AddWebcamsToolbarButton(); }
/// <summary> /// Adds image to cache /// </summary> /// <param name="iconDescription">weather icon description to store image for</param> /// <param name="imageData">image data to store</param> /// <returns>task to wait on</returns> public async Task AddImageAsync(WeatherIconDescription iconDescription, byte[] imageData) { string imageId = await GetImageIdentifierAsync(iconDescription); lock (this.imageCacheLock) { this.imageCache[imageId] = new ImageCacheEntry(imageData); } }
/// <summary> /// Maps a weather icon description to an ID in the table managed by this data /// service. /// </summary> /// <param name="weatherIconDescription">weather icon description to find</param> /// <returns>ID from the weather_dashboard_icons table</returns> private async Task <int> IdFromDescription(WeatherIconDescription weatherIconDescription) { var resultList = await this.connection.Table <WeatherIconDescriptionEntry>() .Where(entry => entry.Group == weatherIconDescription.Group && entry.Name == weatherIconDescription.Name && entry.WebLink == weatherIconDescription.WebLink) .ToListAsync(); return(resultList.FirstOrDefault()?.Id ?? -1); }
/// <summary> /// Called when a weather icon should be added to the dashboard /// </summary> /// <param name="iconDescription">weather icon description</param> /// <returns>task to wait on</returns> public async Task AddWeatherIcon(WeatherIconDescription iconDescription) { // remove it when it's already in the list, in order to move it to the end this.weatherIconDescriptionList.RemoveAll( x => x.Type == iconDescription.Type && x.WebLink == iconDescription.WebLink); this.weatherIconDescriptionList.Add(iconDescription); await this.SaveWeatherIconListAsync(); this.UpdateWeatherDashboardItems(); }
/// <summary> /// Returns an image from image cache /// </summary> /// <param name="iconDescription">weather icon description to load image for</param> /// <returns>image source, or null when no image was found or could be loaded</returns> public static async Task <ImageSource> GetImageAsync(WeatherIconDescription iconDescription) { switch (iconDescription.Type) { case WeatherIconDescription.IconType.IconLink: if (iconDescription.WebLink.StartsWith("https://www.austrocontrol.at")) { return(new StreamImageSource() { Stream = (cancellationToken) => { var platform = DependencyService.Get <IPlatform>(); return Task.FromResult(platform.OpenAssetStream("alptherm-favicon.png")); } }); } string faviconLink = await GetFaviconFromLinkAsync(iconDescription.WebLink); if (!string.IsNullOrEmpty(faviconLink)) { return(new UriImageSource { Uri = new Uri(faviconLink) }); } break; case WeatherIconDescription.IconType.IconApp: return(new StreamImageSource() { Stream = (cancellationToken) => { var appManager = DependencyService.Get <IAppManager>(); byte[] appIconData = appManager.GetAppIcon(iconDescription.WebLink); return Task.FromResult <Stream>(new MemoryStream(appIconData)); } }); case WeatherIconDescription.IconType.IconPlaceholder: return(SvgImageCache.GetImageSource("icons/border-none-variant.svg")); default: break; } return(null); }
public async Task TestIconTypePlaceholder() { // set up var placeholderIcon = new WeatherIconDescription { Name = "placeholder", Type = WeatherIconDescription.IconType.IconPlaceholder, }; // run var imageSource = await WeatherImageCache.GetImageAsync(placeholderIcon); // check Assert.IsNotNull(imageSource, "returned image source must not be null"); }
/// <summary> /// Loads image with given image ID and weather icon description /// </summary> /// <param name="imageId">image ID to load</param> /// <param name="iconDescription">icon description for image to load</param> /// <returns>task to wait on</returns> private async Task LoadImageAsync(string imageId, WeatherIconDescription iconDescription) { ImageCacheEntry entry = null; switch (iconDescription.Type) { case WeatherIconDescription.IconType.IconLink: if (iconDescription.WebLink.StartsWith("https://www.austrocontrol.at")) { var platform = DependencyService.Get <IPlatform>(); byte[] data = platform.LoadAssetBinaryData("alptherm-favicon.png"); entry = new ImageCacheEntry(data); break; } string faviconLink = await GetFaviconFromLinkAsync(iconDescription.WebLink); if (!string.IsNullOrEmpty(faviconLink)) { byte[] data = await this.client.GetByteArrayAsync(faviconLink); entry = new ImageCacheEntry(data); } break; case WeatherIconDescription.IconType.IconApp: var appManager = DependencyService.Get <IAppManager>(); entry = new ImageCacheEntry(appManager.GetAppIcon(iconDescription.WebLink)); break; case WeatherIconDescription.IconType.IconPlaceholder: string imagePath = Converter.ImagePathConverter.GetDeviceDependentImage("border_none_variant"); entry = new ImageCacheEntry(ImageSource.FromFile(imagePath)); break; default: break; } if (entry != null) { lock (this.imageCacheLock) { this.imageCache[imageId] = entry; } } }
public void TestDefaultCtor() { // set up var iconDescription = new WeatherIconDescription { Name = "TestLink", Type = WeatherIconDescription.IconType.IconLink, WebLink = "https://localhost/test/123/" }; // run var page = new WeatherDetailsPage(iconDescription); // check Assert.IsTrue(page.Title.Length > 0, "page title must have been set"); }
public async Task TestBuiltInIconLink() { // set up var desc = new WeatherIconDescription { Name = "austrocontrol", Type = WeatherIconDescription.IconType.IconLink, WebLink = "https://www.austrocontrol.at", }; // run var imageSource = await WeatherImageCache.GetImageAsync(desc); // check Assert.IsNotNull(imageSource, "returned image source must not be null"); }
public async Task TestIconTypeIconLink() { // set up var desc = new WeatherIconDescription { Name = "hello world", Type = WeatherIconDescription.IconType.IconLink, WebLink = "https://localhost/test/123/", }; // run var imageSource = await WeatherImageCache.GetImageAsync(desc); // check Assert.IsNotNull(imageSource, "returned image source must not be null"); }
/// <summary> /// Called when a weather icon should be added to the dashboard /// </summary> /// <param name="sender">sender; always null</param> /// <param name="iconDescription">weather icon description</param> private void OnAddWeatherIcon(object sender, WeatherIconDescription iconDescription) { // remove it when it's already in the list, in order to move it to the end this.WeatherIconDescriptionList.RemoveAll( x => x.Type == iconDescription.Type && x.WebLink == iconDescription.WebLink); int insertIndex = this.WeatherIconDescriptionList.Any() ? this.WeatherIconDescriptionList.Count - 1 : 0; this.WeatherIconDescriptionList.Insert(insertIndex, iconDescription); this.OnPropertyChanged(nameof(this.WeatherIconDescriptionList)); Task.Run(async() => { await this.SaveWeatherIconListAsync(); }); }
public void TestTappedIconTypeIconLink() { // set up var description = new WeatherIconDescription { Name = "Windy", Type = WeatherIconDescription.IconType.IconLink, WebLink = "https://localhost/test/123/" }; // run var viewModel = new WeatherIconViewModel(null, description); Assert.IsTrue(viewModel.Tapped.CanExecute(null), "command must be able to executed"); viewModel.Tapped.Execute(null); // can't check result }
/// <summary> /// Returns an image from image cache /// </summary> /// <param name="iconDescription">weather icon description to load image for</param> /// <returns>image source, or null when no image was found or could be loaded</returns> public async Task <ImageSource> GetImageAsync(WeatherIconDescription iconDescription) { string imageId = await GetImageIdentifierAsync(iconDescription); bool containsImage; lock (this.imageCacheLock) { containsImage = this.imageCache.ContainsKey(imageId); } if (!containsImage) { await this.LoadImageAsync(imageId, iconDescription); } lock (this.imageCacheLock) { return(this.imageCache.ContainsKey(imageId) ? this.imageCache[imageId].Source ?? null : null); } }
public void TestTappedIconTypeIconApp() { // set up var description = new WeatherIconDescription { Name = "Windy", Type = WeatherIconDescription.IconType.IconApp, WebLink = "com.windyty.android" }; // run var viewModel = new WeatherIconViewModel(null, description); Assert.IsTrue(viewModel.Tapped.CanExecute(null), "command must be able to executed"); viewModel.Tapped.Execute(null); // check var appManager = DependencyService.Get <IAppManager>() as UnitTestAppManager; Assert.IsTrue(appManager.AppHasBeenOpened, "app must have been opened"); }
public void TestDefaultCtor() { // set up var description = new WeatherIconDescription { Name = "Windy", Type = WeatherIconDescription.IconType.IconApp, WebLink = "com.windyty.android" }; // run var viewModel = new WeatherIconViewModel(null, description); ////Assert.IsTrue( //// viewModel.WaitForPropertyChange( //// nameof(viewModel.Icon), //// TimeSpan.FromSeconds(10)), //// "waiting for property change must succeed"); // check Assert.AreEqual(description.Name, viewModel.Title, "title must match name of description"); ////Assert.IsNotNull(viewModel.Icon, "icon image source must not be null"); Assert.IsNotNull(viewModel.Tapped, "Tapped command must not be null"); }
/// <summary> /// Called when the user clicked on the "add web link" button /// </summary> /// <returns>task to wait on</returns> private async Task AddWebLinkAsync() { WeatherIconDescription weatherIconDescription = await AddWeatherLinkPopupPage.ShowAsync(); if (weatherIconDescription == null) { return; } var dataService = DependencyService.Get <IDataService>(); var weatherIconDescriptionDataService = dataService.GetWeatherIconDescriptionDataService(); await weatherIconDescriptionDataService.Add(weatherIconDescription); int insertIndex = this.WeatherDashboardItems.Any() ? this.WeatherDashboardItems.Count - 1 : 0; this.WeatherDashboardItems.Insert( insertIndex, new WeatherIconViewModel(this.AddIconAsync, weatherIconDescription)); this.OnPropertyChanged(nameof(this.WeatherDashboardItems)); }
/// <summary> /// Creates a new weather icon instance /// </summary> /// <param name="iconDescription">weather icon description</param> public WeatherIcon(WeatherIconDescription iconDescription) { this.BindingContext = this.viewModel = new WeatherIconViewModel(iconDescription); this.InitializeComponent(); }
/// <summary> /// Called from SelectWeatherIconPage when a weather icon was selected by the user. /// </summary> /// <param name="weatherIcon">selected weather icon</param> private void OnSelectedWeatherIcon(WeatherIconDescription weatherIcon) { AddWeatherIcon(this, weatherIcon); App.RunOnUiThread(async() => await NavigationService.Instance.GoBack()); }
/// <summary> /// Adds new weather icon to dashboard; called by SelectWeatherIconViewModel /// </summary> /// <param name="sender">sender object; must not be null</param> /// <param name="iconDescription">weather icon description</param> public static void AddWeatherIcon(object sender, WeatherIconDescription iconDescription) { MessagingCenter.Send <object, WeatherIconDescription>(sender, MessageAddWeatherIcon, iconDescription); }