File: gitg-avatar-cache.vala

package info (click to toggle)
gitg 41-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 18,876 kB
  • sloc: ansic: 1,636; ruby: 1,445; sh: 314; python: 261; xml: 57; makefile: 15
file content (127 lines) | stat: -rw-r--r-- 3,041 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
 * This file is part of gitg
 *
 * Copyright (C) 2013 - Jesse van den Kieboom
 *
 * gitg is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * gitg is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with gitg. If not, see <http://www.gnu.org/licenses/>.
 */

public class Gitg.AvatarCache : Object
{
	private Gee.HashMap<string, Gdk.Pixbuf?> d_cache;
	private static AvatarCache? s_instance;

	construct
	{
		d_cache = new Gee.HashMap<string, Gdk.Pixbuf>();
	}

	private AvatarCache()
	{
		Object();
	}

	public static AvatarCache @default()
	{
		if (s_instance == null)
		{
			s_instance = new AvatarCache();
		}

		return s_instance;
	}

	public async Gdk.Pixbuf? load(string email, int size = 50, Cancellable? cancellable = null)
	{
		var id = Checksum.compute_for_string(ChecksumType.MD5, email.down());

		var ckey = @"$id $size";

		if (d_cache.has_key(ckey))
		{
			return d_cache[ckey];
		}

		var gravatar = @"https://www.gravatar.com/avatar/$(id)?d=404&s=$(size)";
		var gfile = File.new_for_uri(gravatar);

		var pixbuf = yield read_avatar_from_file(id, gfile, size, cancellable);

		d_cache[ckey] = pixbuf;
		return pixbuf;
	}

	private async Gdk.Pixbuf? read_avatar_from_file(string       id,
	                                                File         file,
	                                                int          size,
	                                                Cancellable? cancellable)
	{
		InputStream stream;

		try
		{
			stream = yield Gitg.PlatformSupport.http_get(file, cancellable);
		}
		catch(Error e)
		{
			debug("Can not retrieve avatar from %s: %s", file.get_path(), e.message);
			return null;
		}

		uint8[] buffer = new uint8[4096];
		var loader = new Gdk.PixbufLoader();

		loader.set_size(size, size);

		return yield read_avatar(id, stream, buffer, loader, cancellable);
	}

	private async Gdk.Pixbuf? read_avatar(string           id,
	                                      InputStream      stream,
	                                      uint8[]          buffer,
	                                      Gdk.PixbufLoader loader,
	                                      Cancellable?     cancellable)
	{
		ssize_t n;

		try
		{
			n = yield stream.read_async(buffer, Priority.LOW, cancellable);
		}
		catch { return null; }

		if (n != 0)
		{
			try
			{
				loader.write(buffer[0:n]);
			}
			catch { return null; }

			return yield read_avatar(id, stream, buffer, loader, cancellable);
		}
		else
		{
			// Finished reading
			try
			{
				loader.close();
			} catch { return null; }

			return loader.get_pixbuf();
		}
	}
}

// ex: ts=4 noet