Mercurial repo sync
[debian/pino.git] / src / content_view.vala
1 using Gtk;
2 using WebKit;
3 using Gee;
4
5 public class ContentView : GLib.Object {
6         
7         private WebView? view;
8         private ScrolledWindow scroll;
9         protected VScrollbar slider;
10         public Frame frame;
11         private Accounts accounts;
12         private VisualStyle visual_style;
13         private Template tpl;
14         
15         private HashMap<string, string> content_map;
16         private HashMap<string, string> scroll_map;
17         
18         private string current_stream = "";
19         
20         private bool not_more = false;
21         
22         public ContentView(Accounts accounts, VisualStyle visual_style) {
23                 view = new WebView();
24                 view.set_size_request(250, 350);
25                 view.navigation_policy_decision_requested.connect(event_route);
26                 view.settings.enable_default_context_menu = false;
27                 
28                 scroll = new ScrolledWindow(null, null);
29                 scroll.set_policy(PolicyType.AUTOMATIC, PolicyType.AUTOMATIC);
30                 scroll.add(view);
31                 
32                 slider = (VScrollbar)scroll.get_vscrollbar();
33                 
34                 frame = new Frame(null);
35                 frame.add(scroll);
36                 
37                 content_map = new HashMap<string, string>(str_hash, str_equal);
38                 scroll_map = new HashMap<string, string>(str_hash, str_equal);
39                 
40                 view.load_finished.connect((f) => {
41                         update_style();
42                         
43                 });
44                 
45                 //when scroll to the bottom
46                 slider.value_changed.connect(slider_move);
47                 
48                 this.accounts = accounts;
49                 this.visual_style = visual_style;
50                 this.visual_style.changed.connect(update_style);
51                 
52                 tpl = new Template(this.visual_style);
53                 
54                 view.load_string(tpl.render_body(), "text/html", "utf8", "file:///");
55                 
56                 this.accounts.stream_was_updated.connect(generate_list);
57                 
58                 this.accounts.insert_reply.connect(insert_reply);
59         }
60         
61         private void insert_reply(string stream_hash, string status_id, Status status) {
62                 if(stream_hash != current_stream) {
63                         debug("not this stream");
64                         return;
65                 }
66                 
67                 AStream? stream = accounts.stream_from_hash(stream_hash);
68                 if(stream == null) {
69                         debug("can't find this stream");
70                         return;
71                 }
72                 
73                 string result = tpl.render_small_status(status, stream);
74                 result = result.replace("'", "\\'");
75                 debug(result);
76                 
77                 string script = """insert_reply('%s', '%s');""".printf(status_id, result);
78                 script = script.replace("\n", " ");
79                 view.execute_script(script);
80         }
81         
82         private void slider_move() {
83                 double max = slider.adjustment.upper;
84                 double current = slider.get_value();
85                 double scroll_size = slider.adjustment.page_size;
86                 
87                 if(!not_more && current != 0 && current + scroll_size == max) {
88                         debug("need more");
89                         AStream? stream = accounts.stream_from_hash(current_stream);
90                         
91                         if(stream == null)
92                                 return;
93                         
94                         stream.menu_more();
95                 }
96         }
97         
98         private void generate_list(string hash, AStream stream) {
99                 debug(hash);
100                 
101                 if(stream.statuses.size == 0 && stream.statuses_fresh.size == 0)
102                         return;
103                 
104                 string data = tpl.stream_to_list(stream, hash);
105                 data = data.replace("\n", " ");
106                 data = data.replace("'", "\\'");
107                 content_map.set(hash, data);
108                 
109                 if(hash == current_stream)
110                         set_current_list(hash);
111         }
112         
113         public void set_current_list(string? hash) {
114                 if(hash == null)
115                         return;
116                 
117                 not_more = true;
118                 
119                 if(current_stream != "")
120                         scroll_map[current_stream] = slider.get_value().to_string();
121                 
122                 current_stream = hash;
123                 
124                 if(content_map.has_key(hash)) {
125                         //view.load_string(content_map.get(hash), "text/html", "utf8", "file:///");
126                         load_content(content_map.get(hash));
127                 } else {
128                         load_content("empty");
129                 }
130                 
131                 if(scroll_map.has_key(current_stream)) {
132                         slider.set_value(scroll_map[current_stream].to_double());
133                 }
134                 
135                 not_more = false;
136         }
137         
138         protected void load_content(owned string data) {
139                 string script = """set_content('%s');""".printf(data);
140                 view.execute_script(script);
141         }
142         
143         private void update_style() {
144                 view.settings.set_property("default-font-size", visual_style.font_size);
145                 view.settings.set_property("default-font-family", visual_style.font_family);
146                 
147                 string header = tpl.render_header();
148                 
149                 /*
150                 accounts.update_all_streams();
151                 
152                 set_current_list(current_stream);
153                 */
154                 
155                 string script = """change_style("%s");""".printf(header);
156                 script = script.replace("\n", " ");
157                 view.execute_script(script);
158                 
159                 debug("style changed");
160         }
161         
162         private bool event_route(WebFrame p0, NetworkRequest request,
163                 WebNavigationAction action, WebPolicyDecision decision) {
164                 if(request.uri == "")
165                         return false;
166                 
167                 string prot = request.uri.split("://")[0];
168                 string path = request.uri.split("://")[1];
169                 debug(prot);
170                 debug(path);
171                 
172                 if(prot == "file")
173                         return false;
174                 
175                 if(prot == "http" || prot == "https" || prot == "ftp") {
176                         GLib.Pid pid;
177                         GLib.Process.spawn_async(".", {"/usr/bin/xdg-open", request.uri}, null,
178                                 GLib.SpawnFlags.STDOUT_TO_DEV_NULL, null, out pid);
179                         return true;
180                 }
181                 
182                 accounts.new_content_action(prot, path);
183                 
184                 return true;
185         }
186 }