1/* 2 * This file is part of gitg 3 * 4 * Copyright (C) 2013 - Jesse van den Kieboom 5 * 6 * gitg is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * gitg is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with gitg. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20public class Gitg.AvatarCache : Object 21{ 22 private Gee.HashMap<string, Gdk.Pixbuf?> d_cache; 23 private static AvatarCache? s_instance; 24 25 construct 26 { 27 d_cache = new Gee.HashMap<string, Gdk.Pixbuf>(); 28 } 29 30 private AvatarCache() 31 { 32 Object(); 33 } 34 35 public static AvatarCache @default() 36 { 37 if (s_instance == null) 38 { 39 s_instance = new AvatarCache(); 40 } 41 42 return s_instance; 43 } 44 45 public async Gdk.Pixbuf? load(string email, int size = 50, Cancellable? cancellable = null) 46 { 47 var id = Checksum.compute_for_string(ChecksumType.MD5, email.down()); 48 49 var ckey = @"$id $size"; 50 51 if (d_cache.has_key(ckey)) 52 { 53 return d_cache[ckey]; 54 } 55 56 var gravatar = @"https://www.gravatar.com/avatar/$(id)?d=404&s=$(size)"; 57 var gfile = File.new_for_uri(gravatar); 58 59 var pixbuf = yield read_avatar_from_file(id, gfile, size, cancellable); 60 61 d_cache[ckey] = pixbuf; 62 return pixbuf; 63 } 64 65 private async Gdk.Pixbuf? read_avatar_from_file(string id, 66 File file, 67 int size, 68 Cancellable? cancellable) 69 { 70 InputStream stream; 71 72 try 73 { 74 stream = yield Gitg.PlatformSupport.http_get(file, cancellable); 75 } 76 catch(Error e) 77 { 78 warning("Can not retrieve avatar from %s: %s", file.get_path(), e.message); 79 return null; 80 } 81 82 uint8[] buffer = new uint8[4096]; 83 var loader = new Gdk.PixbufLoader(); 84 85 loader.set_size(size, size); 86 87 return yield read_avatar(id, stream, buffer, loader, cancellable); 88 } 89 90 private async Gdk.Pixbuf? read_avatar(string id, 91 InputStream stream, 92 uint8[] buffer, 93 Gdk.PixbufLoader loader, 94 Cancellable? cancellable) 95 { 96 ssize_t n; 97 98 try 99 { 100 n = yield stream.read_async(buffer, Priority.LOW, cancellable); 101 } 102 catch { return null; } 103 104 if (n != 0) 105 { 106 try 107 { 108 loader.write(buffer[0:n]); 109 } 110 catch { return null; } 111 112 return yield read_avatar(id, stream, buffer, loader, cancellable); 113 } 114 else 115 { 116 // Finished reading 117 try 118 { 119 loader.close(); 120 } catch { return null; } 121 122 return loader.get_pixbuf(); 123 } 124 } 125} 126 127// ex: ts=4 noet 128