/// <summary> /// Gets a stream containing all concatenated javascript /// </summary> /// <returns>Task{Stream}.</returns> private async Task<Stream> GetAllJavascript(string mode, string culture, string version, bool enableMinification) { var memoryStream = new MemoryStream(); var newLineBytes = Encoding.UTF8.GetBytes(Environment.NewLine); await AppendResource(memoryStream, "bower_components/jquery/dist/jquery.min.js", newLineBytes).ConfigureAwait(false); //await AppendLocalization(memoryStream, culture, excludePhrases).ConfigureAwait(false); await memoryStream.WriteAsync(newLineBytes, 0, newLineBytes.Length).ConfigureAwait(false); if (!string.IsNullOrWhiteSpace(mode)) { var appModeBytes = Encoding.UTF8.GetBytes(string.Format("window.appMode='{0}';", mode)); await memoryStream.WriteAsync(appModeBytes, 0, appModeBytes.Length).ConfigureAwait(false); } // Write the version string for the dashboard comparison function var versionString = string.Format("window.dashboardVersion='{0}';", version); var versionBytes = Encoding.UTF8.GetBytes(versionString); await memoryStream.WriteAsync(versionBytes, 0, versionBytes.Length).ConfigureAwait(false); await memoryStream.WriteAsync(newLineBytes, 0, newLineBytes.Length).ConfigureAwait(false); var builder = new StringBuilder(); var commonFiles = new[] { "bower_components/requirejs/require.js", "thirdparty/jquerymobile-1.4.5/jquery.mobile.custom.js", "thirdparty/browser.js", "thirdparty/jquery.unveil-custom.js", "apiclient/logger.js", "apiclient/md5.js", "apiclient/sha1.js", "apiclient/store.js", "apiclient/device.js", "apiclient/credentials.js", "apiclient/ajax.js", "apiclient/events.js", "apiclient/deferred.js", "apiclient/apiclient.js" }.ToList(); commonFiles.Add("apiclient/connectionmanager.js"); foreach (var file in commonFiles) { using (var fs = _fileSystem.GetFileStream(GetDashboardResourcePath(file), FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true)) { using (var streamReader = new StreamReader(fs)) { var text = await streamReader.ReadToEndAsync().ConfigureAwait(false); builder.Append(text); builder.Append(Environment.NewLine); } } } foreach (var file in GetScriptFiles()) { var path = GetDashboardResourcePath("scripts/" + file); using (var fs = _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true)) { using (var streamReader = new StreamReader(fs)) { var text = await streamReader.ReadToEndAsync().ConfigureAwait(false); builder.Append(text); builder.Append(Environment.NewLine); } } } var js = builder.ToString(); if (enableMinification) { try { var result = new CrockfordJsMinifier().Minify(js, false, Encoding.UTF8); if (result.Errors.Count > 0) { _logger.Error("Error minifying javascript: " + result.Errors[0].Message); } else { js = result.MinifiedContent; } } catch (Exception ex) { _logger.ErrorException("Error minifying javascript", ex); } } var bytes = Encoding.UTF8.GetBytes(js); await memoryStream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); memoryStream.Position = 0; return memoryStream; }
/// <summary> /// Gets all CSS. /// </summary> /// <returns>Task{Stream}.</returns> private async Task<Stream> GetAllCss(bool enableMinification) { var memoryStream = new MemoryStream(); var files = new[] { "thirdparty/jquerymobile-1.4.5/jquery.mobile.custom.theme.css", "thirdparty/jquerymobile-1.4.5/jquery.mobile.custom.structure.css", "css/site.css", "css/chromecast.css", "css/nowplayingbar.css", "css/mediaplayer.css", "css/mediaplayer-video.css", "css/librarymenu.css", "css/librarybrowser.css", "css/card.css", "css/notifications.css", "css/search.css", "css/remotecontrol.css", "css/userimage.css", "css/nowplaying.css", "css/materialize.css", "thirdparty/paper-button-style.css" }; var builder = new StringBuilder(); foreach (var file in files) { var path = GetDashboardResourcePath(file); using (var fs = _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true)) { using (var streamReader = new StreamReader(fs)) { var text = await streamReader.ReadToEndAsync().ConfigureAwait(false); builder.Append(text); builder.Append(Environment.NewLine); } } } var css = builder.ToString(); if (enableMinification) { try { var result = new KristensenCssMinifier().Minify(builder.ToString(), false, Encoding.UTF8); if (result.Errors.Count > 0) { _logger.Error("Error minifying css: " + result.Errors[0].Message); } else { css = result.MinifiedContent; } } catch (Exception ex) { _logger.ErrorException("Error minifying css", ex); } } var bytes = Encoding.UTF8.GetBytes(css); memoryStream.Write(bytes, 0, bytes.Length); memoryStream.Position = 0; return memoryStream; }
/// <summary> /// Modifies the HTML by adding common meta tags, css and js. /// </summary> /// <param name="sourceStream">The source stream.</param> /// <param name="mode">The mode.</param> /// <param name="appVersion">The application version.</param> /// <param name="localizationCulture">The localization culture.</param> /// <param name="enableMinification">if set to <c>true</c> [enable minification].</param> /// <returns>Task{Stream}.</returns> public async Task<Stream> ModifyHtml(Stream sourceStream, string mode, string appVersion, string localizationCulture, bool enableMinification) { using (sourceStream) { string html; using (var memoryStream = new MemoryStream()) { await sourceStream.CopyToAsync(memoryStream).ConfigureAwait(false); html = Encoding.UTF8.GetString(memoryStream.ToArray()); if (string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase)) { html = ModifyForCordova(html); } if (!string.IsNullOrWhiteSpace(localizationCulture)) { var lang = localizationCulture.Split('-').FirstOrDefault(); html = html.Replace("<html>", "<html data-culture=\"" + localizationCulture + "\" lang=\"" + lang + "\">"); } if (enableMinification) { try { var minifier = new HtmlMinifier(new HtmlMinificationSettings { AttributeQuotesRemovalMode = HtmlAttributeQuotesRemovalMode.KeepQuotes, RemoveOptionalEndTags = false, RemoveTagsWithoutContent = false }); var result = minifier.Minify(html, false); if (result.Errors.Count > 0) { _logger.Error("Error minifying html: " + result.Errors[0].Message); } else { html = result.MinifiedContent; } } catch (Exception ex) { _logger.ErrorException("Error minifying html", ex); } } html = html.Replace("<body>", "<body><paper-drawer-panel class=\"mainDrawerPanel mainDrawerPanelPreInit\" forceNarrow><div class=\"mainDrawer\" drawer></div><div class=\"mainDrawerPanelContent\" main><!--<div class=\"pageContainer\">") .Replace("</body>", "</div>--></div></paper-drawer-panel></body>"); } var versionString = !string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase) ? "?v=" + appVersion : string.Empty; var imports = new[] { "vulcanize-out.html" + versionString }; var importsHtml = string.Join("", imports.Select(i => "<link rel=\"import\" href=\"" + i + "\">").ToArray()); // It would be better to make polymer completely dynamic and loaded on demand, but seeing issues with that // In chrome it is causing the body to be hidden while loading, which leads to width-check methods to return 0 for everything //imports = ""; html = html.Replace("<head>", "<head>" + GetMetaTags(mode) + GetCommonCss(mode, appVersion)); html = html.Replace("</body>", GetInitialJavascript(mode, appVersion) + importsHtml + GetCommonJavascript(mode, appVersion) + "</body>"); var bytes = Encoding.UTF8.GetBytes(html); return new MemoryStream(bytes); } }
/// <summary> /// Gets the common CSS. /// </summary> /// <param name="mode">The mode.</param> /// <param name="version">The version.</param> /// <returns>System.String.</returns> private string GetCommonCss(string mode, string version) { var versionString = !string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase) ? "?v=" + version : string.Empty; var files = new[] { "css/all.css" + versionString }; var tags = files.Select(s => string.Format("<link rel=\"stylesheet\" href=\"{0}\" />", s)).ToArray(); return string.Join(string.Empty, tags); }
/// <summary> /// Gets all CSS. /// </summary> /// <returns>Task{Stream}.</returns> private async Task<Stream> GetAllCss() { var files = new[] { "site.css", "chromecast.css", "mediaplayer.css", "mediaplayer-video.css", "librarymenu.css", "librarybrowser.css", "detailtable.css", "card.css", "tileitem.css", "metadataeditor.css", "notifications.css", "search.css", "pluginupdates.css", "remotecontrol.css", "userimage.css", "livetv.css", "nowplaying.css", "icons.css" }; var builder = new StringBuilder(); foreach (var file in files) { var path = GetDashboardResourcePath("css/" + file); using (var fs = _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true)) { using (var streamReader = new StreamReader(fs)) { var text = await streamReader.ReadToEndAsync().ConfigureAwait(false); builder.Append(text); builder.Append(Environment.NewLine); } } } var css = builder.ToString(); //try //{ // var result = new KristensenCssMinifier().Minify(builder.ToString(), false, Encoding.UTF8); // css = result.MinifiedContent; //} //catch (Exception ex) //{ // Logger.ErrorException("Error minifying css", ex); //} var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(css)); memoryStream.Position = 0; return memoryStream; }
/// <summary> /// Gets the common javascript. /// </summary> /// <param name="version">The version.</param> /// <returns>System.String.</returns> private string GetCommonJavascript(Version version) { var builder = new StringBuilder(); var versionString = "?v=" + version; var files = new[] { "scripts/all.js" + versionString, "thirdparty/jstree1.0/jquery.jstree.min.js", "thirdparty/swipebox-master/js/jquery.swipebox.min.js" + versionString }; var tags = files.Select(s => string.Format("<script src=\"{0}\"></script>", s)).ToArray(); builder.Append(string.Join(string.Empty, tags)); return builder.ToString(); }
/// <summary> /// Gets the common CSS. /// </summary> /// <param name="version">The version.</param> /// <returns>System.String.</returns> private string GetCommonCss(Version version) { var versionString = "?v=" + version; var files = new[] { "thirdparty/jquerymobile-1.4.5/jquery.mobile-1.4.5.min.css", "thirdparty/swipebox-master/css/swipebox.min.css" + versionString, "css/all.css" + versionString }; var tags = files.Select(s => string.Format("<link rel=\"stylesheet\" href=\"{0}\" />", s)).ToArray(); return string.Join(string.Empty, tags); }
/// <summary> /// Gets the common CSS. /// </summary> /// <param name="mode">The mode.</param> /// <param name="version">The version.</param> /// <returns>System.String.</returns> private string GetCommonCss(string mode, Version version) { var versionString = !string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase) ? "?v=" + version : string.Empty; var files = new[] { "thirdparty/jquerymobile-1.4.5/jquery.mobile-1.4.5.min.css", "thirdparty/fontawesome/css/font-awesome.min.css" + versionString, "thirdparty/materialicons/style.css" + versionString, "css/all.css" + versionString }; var tags = files.Select(s => string.Format("<link rel=\"stylesheet\" href=\"{0}\" />", s)).ToArray(); return string.Join(string.Empty, tags); }
/// <summary> /// Determines whether [is multi disc album folder] [the specified path]. /// </summary> /// <param name="path">The path.</param> /// <returns><c>true</c> if [is multi disc album folder] [the specified path]; otherwise, <c>false</c>.</returns> public static bool IsMultiDiscAlbumFolder(string path) { var filename = Path.GetFileName(path); if (string.IsNullOrWhiteSpace(filename)) { return false; } // Normalize // Remove whitespace filename = filename.Replace("-", string.Empty); filename = Regex.Replace(filename, @"\s+", ""); var prefixes = new[] { "disc", "cd", "disk" }; foreach (var prefix in prefixes) { if (filename.IndexOf(prefix, StringComparison.OrdinalIgnoreCase) == 0) { var tmp = filename.Substring(prefix.Length); int val; if (int.TryParse(tmp, NumberStyles.Any, CultureInfo.InvariantCulture, out val)) { return true; } } } return false; }