diff --git a/ClientServerLib/ClientServerLib/CServer.cs b/ClientServerLib/ClientServerLib/CServer.cs index 07dec143..3ae61191 100644 --- a/ClientServerLib/ClientServerLib/CServer.cs +++ b/ClientServerLib/ClientServerLib/CServer.cs @@ -68,6 +68,13 @@ namespace ServerLib set { CServer.getSiteFile = value; } } + private static GetDelayedImageDelegate getDelayedImage; + public static GetDelayedImageDelegate GetDelayedImage + { + internal get { return CServer.getDelayedImage; } + set { CServer.getDelayedImage = value; } + } + #endregion #region songs diff --git a/ClientServerLib/ClientServerLib/CWebservice.cs b/ClientServerLib/ClientServerLib/CWebservice.cs index 5bbfa3a9..272fc025 100644 --- a/ClientServerLib/ClientServerLib/CWebservice.cs +++ b/ClientServerLib/ClientServerLib/CWebservice.cs @@ -96,6 +96,12 @@ namespace ServerLib UriTemplate = "/img/{filename}")] Stream GetImgFile(String filename); + [OperationContract] + [WebInvoke(Method = "GET", + ResponseFormat = WebMessageFormat.Json, + UriTemplate = "/delayedImage?id={id}")] + Base64Image GetDelayedImage(String id); + #endregion #region songs @@ -382,6 +388,11 @@ namespace ServerLib } } + public Base64Image GetDelayedImage(string id) + { + return CServer.GetDelayedImage(id); + } + #endregion #region songs diff --git a/ClientServerLib/ClientServerLib/DataStructs.cs b/ClientServerLib/ClientServerLib/DataStructs.cs index 894c2a28..ccd9a1a4 100644 --- a/ClientServerLib/ClientServerLib/DataStructs.cs +++ b/ClientServerLib/ClientServerLib/DataStructs.cs @@ -58,6 +58,8 @@ namespace ServerLib public delegate byte[] GetSiteFileDelegate(string filename); + public delegate Base64Image GetDelayedImageDelegate(string hashedFilename); + #endregion [DataContract] @@ -66,6 +68,9 @@ namespace ServerLib [DataMember] private string base64Data = ""; + [DataMember] + private string imageId = ""; + public Base64Image(Image img, ImageFormat format) { MemoryStream ms = new MemoryStream(); @@ -74,6 +79,11 @@ namespace ServerLib base64Data = "data:image/" + formatString + ";base64," + Convert.ToBase64String(ms.ToArray()); } + public Base64Image(string imageId) + { + this.imageId = imageId; + } + public Image getImage() { string onlyBase64Data = base64Data.Substring(base64Data.IndexOf(";base64,") + (";base64,").Length); diff --git a/Vocaluxe/Base/Server/CVocaluxeServer.cs b/Vocaluxe/Base/Server/CVocaluxeServer.cs index 47f102ed..dcb1c38f 100644 --- a/Vocaluxe/Base/Server/CVocaluxeServer.cs +++ b/Vocaluxe/Base/Server/CVocaluxeServer.cs @@ -46,7 +46,7 @@ namespace Vocaluxe.Base.Server _Clients = new Dictionary(); _Server = new CServer(CConfig.ServerPort, CConfig.ServerEncryption == EOffOn.TR_CONFIG_ON); - //_Server = new CServer(RequestHandler, CConfig.ServerPort, CConfig.ServerPassword); + //TODO: remove CConfig.ServerPassword CServer.SendKeyEvent = sendKeyEvent; CServer.GetProfileData = getProfileData; @@ -62,6 +62,7 @@ namespace Vocaluxe.Base.Server CServer.GetUserRole = getUserRole; CServer.SetUserRole = setUserRole; CServer.GetUserIdFromUsername = getUserIdFromUsername; + CServer.GetDelayedImage = getDelayedImage; _Discover = new CDiscover(CConfig.ServerPort, CCommands.BroadcastKeyword); Controller.Init(); @@ -198,7 +199,7 @@ namespace Vocaluxe.Base.Server else if (newProfile.Avatar == null) { newProfile.Avatar = CProfiles.GetAvatars().First(); - + /*CAvatar avatar = new CAvatar(-1); avatar.LoadFromFile("Profiles\\Avatar_f.png"); CProfiles.AddAvatar(avatar); @@ -262,9 +263,7 @@ namespace Vocaluxe.Base.Server { if (File.Exists(avatar.FileName)) { - Image avatarImage = Image.FromFile(avatar.FileName); - //TODO: Convert??? and Resize? - profileData.Avatar = new Base64Image(avatarImage, avatarImage.RawFormat); + profileData.Avatar = new Base64Image(createDelayedImage(avatar.FileName)); } } return profileData; @@ -315,6 +314,8 @@ namespace Vocaluxe.Base.Server #region website + private static Dictionary delayedImagePath = new Dictionary(); + private static byte[] getSiteFile(string filename) { string path = "Website/" + filename; @@ -335,6 +336,45 @@ namespace Vocaluxe.Base.Server return File.ReadAllBytes(path); } + private static string createDelayedImage(string filename) + { + byte[] by = SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(filename)); + var sb = new StringBuilder(); + foreach (byte b in by) + { + sb.Append(b.ToString("x2")); + } + + string hashedFilename = sb.ToString(); + + if (!delayedImagePath.ContainsKey(hashedFilename)) + { + delayedImagePath.Add(hashedFilename, filename); + } + return hashedFilename; + } + + private static Base64Image getDelayedImage(string hashedFilename) + { + if (!delayedImagePath.ContainsKey(hashedFilename)) + { + throw new FileNotFoundException("Image not found"); + } + + string fileName = delayedImagePath[hashedFilename]; + + if (File.Exists(fileName)) + { + Image image = Image.FromFile(fileName); + return new Base64Image(image, image.RawFormat); + } + else + { + throw new FileNotFoundException("Image not found"); + } + + } + #endregion #region songs @@ -376,8 +416,7 @@ namespace Vocaluxe.Base.Server result.SongId = song.ID; if (includeCover) { - Image cover = Image.FromFile(song.Folder + "\\" + song.CoverFileName); - result.Cover = new Base64Image(cover, cover.RawFormat); + result.Cover = new Base64Image(createDelayedImage(song.Folder + "\\" + song.CoverFileName)); } } return result; diff --git a/Vocaluxe/Website/css/style.css b/Vocaluxe/Website/css/style.css index 8eb2a62b..00a09e82 100644 --- a/Vocaluxe/Website/css/style.css +++ b/Vocaluxe/Website/css/style.css @@ -54,3 +54,12 @@ font-size: 18px; font-weight: bold; } + +.imageLoaderImg { + height:45px; + width:45px; + background: url(images/ajax-loader.gif); + background-size: 46px 46px; + -webkit-border-radius: 36px; + border-radius: 36px; +} \ No newline at end of file diff --git a/Vocaluxe/Website/js/main.js b/Vocaluxe/Website/js/main.js index 36c5c846..e3a6f9e5 100644 --- a/Vocaluxe/Website/js/main.js +++ b/Vocaluxe/Website/js/main.js @@ -132,12 +132,9 @@ function initPageLoadHandler() { function handleDisplayProfileData(data) { $('#playerName').prop("value", data.PlayerName); - if (data.Avatar && data.Avatar.base64Data) { - $('#playerAvatar').prop("src", data.Avatar.base64Data); - } - else { - $('#playerAvatar').prop("src", "img/profile.png"); - } + + addImage($('#playerAvatar')[0], data.Avatar, "img/profile.png"); + $('#playerAvatar').data("changed", false); $('#playerType').prop("value", data.Type); $('#playerDifficulty').prop("value", data.Difficulty); @@ -196,9 +193,12 @@ function initPageLoadHandler() { } for (var profile in data) { - $('
  • ' + data[profile].PlayerName + '

    Click here to show the profile of ' + data[profile].PlayerName + '

  • ') + var img = $('
  • ' + data[profile].PlayerName + '

    Click here to show the profile of ' + data[profile].PlayerName + '

  • ') .appendTo('#selectProfileList') - .click(handleProfileSelectLineClick); + .click(handleProfileSelectLineClick) + .find("img")[0]; + + addImage(img, data[profile].Avatar, "img/profile.png"); } $('#selectProfileList').listview('refresh'); @@ -221,12 +221,7 @@ function initPageLoadHandler() { $('#displaySongTitle').text("No current song"); } - if (result.Cover && result.Cover.base64Data) { - $('#displaySongCover').prop("src", result.Cover.base64Data); - } - else { - $('#displaySongCover').prop("src", "img/noCover.png"); - } + addImage($('#displaySongCover')[0], result.Cover, "img/noCover.png"); if (result.Artist != null) { $('#displaySongArtist').text(result.Artist); @@ -549,3 +544,44 @@ function initKeyboardPageHandler() { } }); } + +var cachedImages = {}; + +function delayedImageLoad(elem, id, fail) { + if (elem && id) { + if (cachedImages[id]) { + elem.src = cachedImages[id].base64Data; + return; + } + + elem.src = ""; + $(elem).addClass("imageLoaderImg"); + $.ajax({ + url: "delayedImage?id=" + id, + headers: { "session": sessionId } + }).done(function (result) { + $(elem).removeClass("imageLoaderImg"); + elem.src = result.base64Data; + cachedImages[id] = result; + }).fail(function () { + $(elem).removeClass("imageLoaderImg"); + if (fail) { + elem.src = fail; + } + }); + } +} + +function addImage(img, base64Image, defaultImg) { + if (base64Image && (base64Image.base64Data || base64Image.imageId)) { + if (base64Image.base64Data) { + $(img).prop("src", base64Image.base64Data); + } + else { + delayedImageLoad(img, base64Image.imageId, defaultImg) + } + } + else { + $(img).prop("src", defaultImg); + } +}