Merge: Added contributing guidelines and link from readme
[nit.git] / contrib / benitlux / src / client / base.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # Common services for the Benitlux app
16 module base
17
18 import app::ui
19 import app::data_store
20 import app::http_request
21 import android::aware
22 import json::serialization
23
24 import benitlux_model
25 import translations
26
27 # Show debug output?
28 fun debug: Bool do return true
29
30 # Root URI of the remote RESTfule server
31 fun benitlux_rest_server_uri: String do return "http://localhost:8080/"
32
33 redef class App
34
35 # Current connection token, or "none"
36 var token: String is lazy, writable do
37 var token = app.data_store["token"]
38 if token isa String then return token
39 return "none"
40 end
41
42 # Name of the currently logged in user
43 var user: nullable String is lazy, writable do
44 var user = app.data_store["user"]
45 if user isa nullable String then return user
46 return null
47 end
48
49 # Event when user logs in or out
50 fun on_log_in do on_save_state
51
52 redef fun on_save_state
53 do
54 app.data_store["user"] = user
55 app.data_store["token"] = token
56 super
57 end
58
59 # Has this app state been restored yet?
60 var restored = false
61
62 redef fun on_restore_state
63 do
64 super
65
66 # TODO this may happen before the lazy loading above
67 restored = true
68
69 if token != "none" then on_log_in
70 end
71
72 # Show simple feedback to the user on important errors
73 fun feedback(text: Text) do print_error text
74 end
75
76 # Show a notification to the user
77 fun notify(title, content: Text, uniqueness_id: Int)
78 do print "Notification {uniqueness_id}: {title}; {content}"
79
80 # View for an item in a list, like a beer or a person
81 abstract class ItemView
82 super View
83 end
84
85 # Basic async HTTP request for this app
86 #
87 # Note that connection errors are passed to `on_fail`, and
88 # server errors or authentification errors are received by `on_load`
89 # and should be passed to `intercept_error`.
90 class BenitluxHttpRequest
91 super AsyncHttpRequest
92
93 redef fun rest_server_uri do return benitlux_rest_server_uri
94
95 redef var rest_action
96
97 redef fun on_fail(error)
98 do
99 if error isa IOError then
100 # This should be a normal network error like being offline.
101 # Print to log, but don't show to the user.
102 print_error error.class_name
103 else
104 # This could be a deserialization error,
105 # it may be related to an outdated client.
106 # Report to user.
107 print_error "Request Error: {rest_server_uri / rest_action} with {error}"
108 app.feedback "Request Error: {error}"
109 end
110 end
111
112 # Intercept known server side errors
113 fun intercept_error(res: nullable Object): Bool
114 do
115 if res isa BenitluxTokenError then
116 app.token = "none"
117 app.user = null
118 return true
119 else if res isa BenitluxError then
120 feedback((res.user_message or else res.message).t)
121 return true
122 else if res isa Error then
123 feedback res.message.t
124 return true
125 end
126 return false
127 end
128
129 # Show feedback pertinent to the user, defaults to a platform specific popup
130 fun feedback(text: String) do app.feedback text
131 end
132
133 # Async request with services to act on the windows of the app
134 class WindowHttpRequest
135 super BenitluxHttpRequest
136
137 autoinit window, rest_action
138
139 # Type of the related `window`
140 type W: Window
141
142 # `Window` on which to apply the results of this request
143 var window: W
144
145 # `Views` to disable while this request is in progress
146 var affected_views = new Array[View]
147
148 redef fun before do for view in affected_views do view.enabled = false
149
150 redef fun after do for view in affected_views do view.enabled = true
151 end
152
153 redef class Text
154 # Ellipsize `self` so it fits within `max_length` characters
155 #
156 # FIXME Remove this when labels are correctly ellipsized on iOS.
157 fun ellipsize: Text do return self
158 end