flet-geolocator 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of flet-geolocator might be problematic. Click here for more details.

@@ -0,0 +1,133 @@
1
+ Metadata-Version: 2.2
2
+ Name: flet-geolocator
3
+ Version: 0.1.0
4
+ Summary: Geolocator control for Flet
5
+ Author-email: Flet contributors <hello@flet.dev>
6
+ Project-URL: Homepage, https://flet.dev
7
+ Project-URL: Documentation, https://flet.dev/docs/controls/geolocator
8
+ Project-URL: Repository, https://github.com/flet-dev/flet-geolocator
9
+ Project-URL: Issues, https://github.com/flet-dev/flet-geolocator/issues
10
+ Classifier: License :: OSI Approved :: Apache Software License
11
+ Requires-Python: >=3.8
12
+ Description-Content-Type: text/markdown
13
+ Requires-Dist: flet>=0.25.2
14
+
15
+ # Geolocator control for Flet
16
+
17
+ `Geolocator` control for Flet.
18
+
19
+ ## Usage
20
+
21
+ Add `flet-geolocator` as dependency (`pyproject.toml` or `requirements.txt`) to your Flet project.
22
+
23
+ ## Example
24
+
25
+ ```py
26
+
27
+ import flet as ft
28
+
29
+ import flet_geolocator as fg
30
+
31
+
32
+ async def main(page: ft.Page):
33
+ page.scroll = ft.ScrollMode.ADAPTIVE
34
+ page.appbar = ft.AppBar(title=ft.Text("Geolocator Tests"))
35
+
36
+ def handle_position_change(e):
37
+ page.add(ft.Text(f"New position: {e.latitude} {e.longitude}"))
38
+
39
+ gl = fg.Geolocator(
40
+ location_settings=fg.GeolocatorSettings(
41
+ accuracy=fg.GeolocatorPositionAccuracy.LOW
42
+ ),
43
+ on_position_change=handle_position_change,
44
+ on_error=lambda e: page.add(ft.Text(f"Error: {e.data}")),
45
+ )
46
+ page.overlay.append(gl)
47
+
48
+ settings_dlg = lambda handler: ft.AlertDialog(
49
+ adaptive=True,
50
+ title=ft.Text("Opening Location Settings..."),
51
+ content=ft.Text(
52
+ "You are about to be redirected to the location/app settings. "
53
+ "Please locate this app and grant it location permissions."
54
+ ),
55
+ actions=[ft.TextButton(text="Take me there", on_click=handler)],
56
+ actions_alignment=ft.MainAxisAlignment.CENTER,
57
+ )
58
+
59
+ async def handle_permission_request(e):
60
+ p = await gl.request_permission_async(wait_timeout=60)
61
+ page.add(ft.Text(f"request_permission: {p}"))
62
+
63
+ async def handle_get_permission_status(e):
64
+ p = await gl.get_permission_status_async()
65
+ page.add(ft.Text(f"get_permission_status: {p}"))
66
+
67
+ async def handle_get_current_position(e):
68
+ p = await gl.get_current_position_async()
69
+ page.add(ft.Text(f"get_current_position: ({p.latitude}, {p.longitude})"))
70
+
71
+ async def handle_get_last_known_position(e):
72
+ p = await gl.get_last_known_position_async()
73
+ page.add(ft.Text(f"get_last_known_position: ({p.latitude}, {p.longitude})"))
74
+
75
+ async def handle_location_service_enabled(e):
76
+ p = await gl.is_location_service_enabled_async()
77
+ page.add(ft.Text(f"is_location_service_enabled: {p}"))
78
+
79
+ async def handle_open_location_settings(e):
80
+ p = await gl.open_location_settings_async()
81
+ page.close(location_settings_dlg)
82
+ page.add(ft.Text(f"open_location_settings: {p}"))
83
+
84
+ async def handle_open_app_settings(e):
85
+ p = await gl.open_app_settings_async()
86
+ page.close(app_settings_dlg)
87
+ page.add(ft.Text(f"open_app_settings: {p}"))
88
+
89
+ location_settings_dlg = settings_dlg(handle_open_location_settings)
90
+ app_settings_dlg = settings_dlg(handle_open_app_settings)
91
+
92
+ page.add(
93
+ ft.Row(
94
+ wrap=True,
95
+ controls=[
96
+ ft.OutlinedButton(
97
+ "Request Permission",
98
+ on_click=handle_permission_request,
99
+ ),
100
+ ft.OutlinedButton(
101
+ "Get Permission Status",
102
+ on_click=handle_get_permission_status,
103
+ ),
104
+ ft.OutlinedButton(
105
+ "Get Current Position",
106
+ on_click=handle_get_current_position,
107
+ ),
108
+ ft.OutlinedButton(
109
+ "Get Last Known Position",
110
+ visible=False if page.web else True,
111
+ on_click=handle_get_last_known_position,
112
+ ),
113
+ ft.OutlinedButton(
114
+ "Is Location Service Enabled",
115
+ on_click=handle_location_service_enabled,
116
+ ),
117
+ ft.OutlinedButton(
118
+ "Open Location Settings",
119
+ visible=False if page.web else True,
120
+ on_click=lambda e: page.open(location_settings_dlg),
121
+ ),
122
+ ft.OutlinedButton(
123
+ "Open App Settings",
124
+ visible=False if page.web else True,
125
+ on_click=lambda e: page.open(app_settings_dlg),
126
+ ),
127
+ ],
128
+ )
129
+ )
130
+
131
+
132
+ ft.app(main)
133
+ ```
@@ -0,0 +1,119 @@
1
+ # Geolocator control for Flet
2
+
3
+ `Geolocator` control for Flet.
4
+
5
+ ## Usage
6
+
7
+ Add `flet-geolocator` as dependency (`pyproject.toml` or `requirements.txt`) to your Flet project.
8
+
9
+ ## Example
10
+
11
+ ```py
12
+
13
+ import flet as ft
14
+
15
+ import flet_geolocator as fg
16
+
17
+
18
+ async def main(page: ft.Page):
19
+ page.scroll = ft.ScrollMode.ADAPTIVE
20
+ page.appbar = ft.AppBar(title=ft.Text("Geolocator Tests"))
21
+
22
+ def handle_position_change(e):
23
+ page.add(ft.Text(f"New position: {e.latitude} {e.longitude}"))
24
+
25
+ gl = fg.Geolocator(
26
+ location_settings=fg.GeolocatorSettings(
27
+ accuracy=fg.GeolocatorPositionAccuracy.LOW
28
+ ),
29
+ on_position_change=handle_position_change,
30
+ on_error=lambda e: page.add(ft.Text(f"Error: {e.data}")),
31
+ )
32
+ page.overlay.append(gl)
33
+
34
+ settings_dlg = lambda handler: ft.AlertDialog(
35
+ adaptive=True,
36
+ title=ft.Text("Opening Location Settings..."),
37
+ content=ft.Text(
38
+ "You are about to be redirected to the location/app settings. "
39
+ "Please locate this app and grant it location permissions."
40
+ ),
41
+ actions=[ft.TextButton(text="Take me there", on_click=handler)],
42
+ actions_alignment=ft.MainAxisAlignment.CENTER,
43
+ )
44
+
45
+ async def handle_permission_request(e):
46
+ p = await gl.request_permission_async(wait_timeout=60)
47
+ page.add(ft.Text(f"request_permission: {p}"))
48
+
49
+ async def handle_get_permission_status(e):
50
+ p = await gl.get_permission_status_async()
51
+ page.add(ft.Text(f"get_permission_status: {p}"))
52
+
53
+ async def handle_get_current_position(e):
54
+ p = await gl.get_current_position_async()
55
+ page.add(ft.Text(f"get_current_position: ({p.latitude}, {p.longitude})"))
56
+
57
+ async def handle_get_last_known_position(e):
58
+ p = await gl.get_last_known_position_async()
59
+ page.add(ft.Text(f"get_last_known_position: ({p.latitude}, {p.longitude})"))
60
+
61
+ async def handle_location_service_enabled(e):
62
+ p = await gl.is_location_service_enabled_async()
63
+ page.add(ft.Text(f"is_location_service_enabled: {p}"))
64
+
65
+ async def handle_open_location_settings(e):
66
+ p = await gl.open_location_settings_async()
67
+ page.close(location_settings_dlg)
68
+ page.add(ft.Text(f"open_location_settings: {p}"))
69
+
70
+ async def handle_open_app_settings(e):
71
+ p = await gl.open_app_settings_async()
72
+ page.close(app_settings_dlg)
73
+ page.add(ft.Text(f"open_app_settings: {p}"))
74
+
75
+ location_settings_dlg = settings_dlg(handle_open_location_settings)
76
+ app_settings_dlg = settings_dlg(handle_open_app_settings)
77
+
78
+ page.add(
79
+ ft.Row(
80
+ wrap=True,
81
+ controls=[
82
+ ft.OutlinedButton(
83
+ "Request Permission",
84
+ on_click=handle_permission_request,
85
+ ),
86
+ ft.OutlinedButton(
87
+ "Get Permission Status",
88
+ on_click=handle_get_permission_status,
89
+ ),
90
+ ft.OutlinedButton(
91
+ "Get Current Position",
92
+ on_click=handle_get_current_position,
93
+ ),
94
+ ft.OutlinedButton(
95
+ "Get Last Known Position",
96
+ visible=False if page.web else True,
97
+ on_click=handle_get_last_known_position,
98
+ ),
99
+ ft.OutlinedButton(
100
+ "Is Location Service Enabled",
101
+ on_click=handle_location_service_enabled,
102
+ ),
103
+ ft.OutlinedButton(
104
+ "Open Location Settings",
105
+ visible=False if page.web else True,
106
+ on_click=lambda e: page.open(location_settings_dlg),
107
+ ),
108
+ ft.OutlinedButton(
109
+ "Open App Settings",
110
+ visible=False if page.web else True,
111
+ on_click=lambda e: page.open(app_settings_dlg),
112
+ ),
113
+ ],
114
+ )
115
+ )
116
+
117
+
118
+ ft.app(main)
119
+ ```
@@ -0,0 +1,36 @@
1
+ [project]
2
+ name = "flet-geolocator"
3
+ version = "0.1.0"
4
+ description = "Geolocator control for Flet"
5
+ readme = "README.md"
6
+ authors = [
7
+ { name = "Flet contributors", email = "hello@flet.dev" }
8
+ ]
9
+ classifiers = [
10
+ "License :: OSI Approved :: Apache Software License",
11
+ ]
12
+ requires-python = ">=3.8"
13
+ dependencies = [
14
+ "flet>=0.25.2",
15
+ ]
16
+
17
+ [project.urls]
18
+ Homepage = "https://flet.dev"
19
+ Documentation = "https://flet.dev/docs/controls/geolocator"
20
+ Repository = "https://github.com/flet-dev/flet-geolocator"
21
+ Issues = "https://github.com/flet-dev/flet-geolocator/issues"
22
+
23
+ [tool.setuptools.package-data]
24
+ "flutter.flet_geolocator" = ["**/*"]
25
+
26
+ [tool.uv]
27
+ dev-dependencies = [
28
+ "flet[all]>=0.25.2",
29
+ ]
30
+
31
+ [tool.setuptools]
32
+ license-files = []
33
+
34
+ [build-system]
35
+ requires = ["setuptools"]
36
+ build-backend = "setuptools.build_meta"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,12 @@
1
+ from flet_geolocator.geolocator import (
2
+ Geolocator,
3
+ GeolocatorActivityType,
4
+ GeolocatorAndroidSettings,
5
+ GeolocatorAppleSettings,
6
+ GeolocatorPermissionStatus,
7
+ GeolocatorPosition,
8
+ GeolocatorPositionAccuracy,
9
+ GeolocatorPositionChangeEvent,
10
+ GeolocatorSettings,
11
+ GeolocatorWebSettings,
12
+ )
@@ -0,0 +1,340 @@
1
+ import json
2
+ from dataclasses import dataclass
3
+ from enum import Enum
4
+ from typing import Any, Optional
5
+
6
+ from flet.core.control import Control
7
+ from flet.core.control_event import ControlEvent
8
+ from flet.core.event_handler import EventHandler
9
+ from flet.core.ref import Ref
10
+ from flet.core.types import (
11
+ ColorValue,
12
+ DurationValue,
13
+ OptionalControlEventCallable,
14
+ OptionalEventCallable,
15
+ OptionalNumber,
16
+ )
17
+
18
+
19
+ class GeolocatorPositionAccuracy(Enum):
20
+ LOWEST = "lowest"
21
+ LOW = "low"
22
+ MEDIUM = "medium"
23
+ HIGH = "high"
24
+ BEST = "best"
25
+ BEST_FOR_NAVIGATION = "bestForNavigation"
26
+ REDUCED = "reduced"
27
+
28
+
29
+ class GeolocatorPermissionStatus(Enum):
30
+ DENIED = "denied"
31
+ DENIED_FOREVER = "deniedForever"
32
+ WHILE_IN_USE = "whileInUse"
33
+ ALWAYS = "always"
34
+ UNABLE_TO_DETERMINE = "unableToDetermine"
35
+
36
+
37
+ class GeolocatorActivityType(Enum):
38
+ AUTOMOTIVE_NAVIGATION = "automotiveNavigation"
39
+ FITNESS = "fitness"
40
+ OTHER_NAVIGATION = "otherNavigation"
41
+ AIRBORNE = "airborne"
42
+ OTHER = "other"
43
+
44
+
45
+ @dataclass
46
+ class GeolocatorPosition:
47
+ latitude: OptionalNumber = None
48
+ longitude: OptionalNumber = None
49
+ speed: OptionalNumber = None
50
+ altitude: OptionalNumber = None
51
+ timestamp: OptionalNumber = None
52
+ accuracy: OptionalNumber = None
53
+ altitude_accuracy: OptionalNumber = None
54
+ heading: OptionalNumber = None
55
+ heading_accuracy: OptionalNumber = None
56
+ speed_accuracy: OptionalNumber = None
57
+ floor: Optional[int] = None
58
+ is_mocked: Optional[bool] = None
59
+
60
+
61
+ @dataclass
62
+ class GeolocatorSettings:
63
+ accuracy: Optional[GeolocatorPositionAccuracy] = None
64
+ distance_filter: Optional[int] = None
65
+ time_limit: DurationValue = None
66
+
67
+
68
+ @dataclass
69
+ class GeolocatorWebSettings(GeolocatorSettings):
70
+ maximum_age: DurationValue = None
71
+
72
+
73
+ @dataclass
74
+ class GeolocatorAppleSettings(GeolocatorSettings):
75
+ activity_type: Optional[GeolocatorActivityType] = None
76
+ pause_location_updates_automatically: Optional[bool] = False
77
+ show_background_location_indicator: Optional[bool] = False
78
+ allow_background_location_updates: Optional[bool] = True
79
+
80
+
81
+ @dataclass
82
+ class GeolocatorAndroidSettings(GeolocatorSettings):
83
+ force_location_manager: Optional[bool] = False
84
+ interval_duration: DurationValue = False
85
+ foreground_notification_text: Optional[str] = None
86
+ foreground_notification_title: Optional[str] = None
87
+ foreground_notification_channel_name: Optional[str] = "Background Location"
88
+ foreground_notification_enable_wake_lock: Optional[bool] = False
89
+ foreground_notification_enable_wifi_lock: Optional[bool] = False
90
+ foreground_notification_set_ongoing: Optional[bool] = False
91
+ foreground_notification_color: Optional[ColorValue] = None
92
+
93
+
94
+ class GeolocatorPositionChangeEvent(ControlEvent):
95
+ def __init__(self, e: ControlEvent):
96
+ super().__init__(e.target, e.name, e.data, e.control, e.page)
97
+ d = json.loads(e.data)
98
+ self.latitude: float = d.get("lat")
99
+ self.longitude: float = d.get("long")
100
+
101
+
102
+ class Geolocator(Control):
103
+ """
104
+ A control that allows you to fetch GPS data from your device.
105
+ This control is non-visual and should be added to `page.overlay` list.
106
+
107
+ -----
108
+
109
+ Online docs: https://flet.dev/docs/controls/geolocator
110
+ """
111
+
112
+ def __init__(
113
+ self,
114
+ # Control
115
+ #
116
+ ref: Optional[Ref] = None,
117
+ data: Any = None,
118
+ location_settings: Optional[GeolocatorSettings] = None,
119
+ on_position_change: OptionalEventCallable[GeolocatorPositionChangeEvent] = None,
120
+ on_error: OptionalControlEventCallable = None,
121
+ ):
122
+ Control.__init__(
123
+ self,
124
+ ref=ref,
125
+ data=data,
126
+ )
127
+ self.__on_position_change = EventHandler(
128
+ lambda e: GeolocatorPositionChangeEvent(e)
129
+ )
130
+ self._add_event_handler(
131
+ "positionChange", self.__on_position_change.get_handler()
132
+ )
133
+ self.on_position_change = on_position_change
134
+ self.on_error = on_error
135
+ self.location_settings = location_settings
136
+
137
+ def _get_control_name(self):
138
+ return "geolocator"
139
+
140
+ def before_update(self):
141
+ self._set_attr_json("locationSettings", self.location_settings)
142
+
143
+ def get_current_position(
144
+ self,
145
+ accuracy: Optional[
146
+ GeolocatorPositionAccuracy
147
+ ] = GeolocatorPositionAccuracy.BEST,
148
+ location_settings: Optional[GeolocatorSettings] = None,
149
+ wait_timeout: Optional[float] = 25,
150
+ ) -> GeolocatorPosition:
151
+ ls = (
152
+ location_settings
153
+ or self.location_settings
154
+ or GeolocatorSettings(accuracy=accuracy)
155
+ )
156
+ output = self.invoke_method(
157
+ "get_current_position",
158
+ {"location_settings": self._convert_attr_json(ls)},
159
+ wait_for_result=True,
160
+ wait_timeout=wait_timeout,
161
+ )
162
+ return (
163
+ GeolocatorPosition(**json.loads(output))
164
+ if output is not None
165
+ else GeolocatorPosition()
166
+ )
167
+
168
+ async def get_current_position_async(
169
+ self,
170
+ accuracy: Optional[
171
+ GeolocatorPositionAccuracy
172
+ ] = GeolocatorPositionAccuracy.BEST,
173
+ location_settings: Optional[GeolocatorSettings] = None,
174
+ wait_timeout: Optional[float] = 25,
175
+ ) -> GeolocatorPosition:
176
+ ls = (
177
+ location_settings
178
+ or self.location_settings
179
+ or GeolocatorSettings(accuracy=accuracy)
180
+ )
181
+ output = await self.invoke_method_async(
182
+ "get_current_position",
183
+ {"location_settings": self._convert_attr_json(ls)},
184
+ wait_for_result=True,
185
+ wait_timeout=wait_timeout,
186
+ )
187
+ return (
188
+ GeolocatorPosition(**json.loads(output))
189
+ if output is not None
190
+ else GeolocatorPosition()
191
+ )
192
+
193
+ def get_last_known_position(
194
+ self,
195
+ wait_timeout: Optional[float] = 25,
196
+ ) -> GeolocatorPosition:
197
+ assert not self.page.web, "get_last_known_position is not supported on web"
198
+ output = self.invoke_method(
199
+ "get_last_known_position",
200
+ wait_for_result=True,
201
+ wait_timeout=wait_timeout,
202
+ )
203
+ return (
204
+ GeolocatorPosition(**json.loads(output))
205
+ if output is not None
206
+ else GeolocatorPosition()
207
+ )
208
+
209
+ async def get_last_known_position_async(
210
+ self,
211
+ wait_timeout: Optional[float] = 25,
212
+ ) -> GeolocatorPosition:
213
+ assert not self.page.web, "get_last_known_position is not supported on web"
214
+ output = await self.invoke_method_async(
215
+ "get_last_known_position",
216
+ wait_for_result=True,
217
+ wait_timeout=wait_timeout,
218
+ )
219
+ return (
220
+ GeolocatorPosition(**json.loads(output))
221
+ if output is not None
222
+ else GeolocatorPosition()
223
+ )
224
+
225
+ def get_permission_status(
226
+ self, wait_timeout: Optional[float] = 25
227
+ ) -> GeolocatorPermissionStatus:
228
+ p = self.invoke_method(
229
+ "get_permission_status",
230
+ wait_for_result=True,
231
+ wait_timeout=wait_timeout,
232
+ )
233
+ return GeolocatorPermissionStatus(p)
234
+
235
+ async def get_permission_status_async(
236
+ self, wait_timeout: Optional[float] = 25
237
+ ) -> GeolocatorPermissionStatus:
238
+ p = await self.invoke_method_async(
239
+ "get_permission_status",
240
+ wait_for_result=True,
241
+ wait_timeout=wait_timeout,
242
+ )
243
+ return GeolocatorPermissionStatus(p)
244
+
245
+ def request_permission(
246
+ self, wait_timeout: Optional[float] = 25
247
+ ) -> GeolocatorPermissionStatus:
248
+ p = self.invoke_method(
249
+ "request_permission",
250
+ wait_for_result=True,
251
+ wait_timeout=wait_timeout,
252
+ )
253
+ return GeolocatorPermissionStatus(p)
254
+
255
+ async def request_permission_async(
256
+ self, wait_timeout: Optional[float] = 25
257
+ ) -> GeolocatorPermissionStatus:
258
+ p = await self.invoke_method_async(
259
+ "request_permission",
260
+ wait_for_result=True,
261
+ wait_timeout=wait_timeout,
262
+ )
263
+ return GeolocatorPermissionStatus(p)
264
+
265
+ def is_location_service_enabled(self, wait_timeout: Optional[float] = 10) -> bool:
266
+ enabled = self.invoke_method(
267
+ "is_location_service_enabled",
268
+ wait_for_result=True,
269
+ wait_timeout=wait_timeout,
270
+ )
271
+ return enabled == "true"
272
+
273
+ async def is_location_service_enabled_async(
274
+ self, wait_timeout: Optional[float] = 10
275
+ ) -> bool:
276
+ enabled = await self.invoke_method_async(
277
+ "is_location_service_enabled",
278
+ wait_for_result=True,
279
+ wait_timeout=wait_timeout,
280
+ )
281
+ return enabled == "true"
282
+
283
+ def open_app_settings(self, wait_timeout: Optional[float] = 10) -> bool:
284
+ assert not self.page.web, "open_app_settings is not supported on web"
285
+ opened = self.invoke_method(
286
+ "open_app_settings",
287
+ wait_for_result=True,
288
+ wait_timeout=wait_timeout,
289
+ )
290
+ return opened == "true"
291
+
292
+ async def open_app_settings_async(self, wait_timeout: Optional[float] = 10) -> bool:
293
+ assert not self.page.web, "open_app_settings is not supported on web"
294
+ opened = await self.invoke_method_async(
295
+ "open_app_settings",
296
+ wait_for_result=True,
297
+ wait_timeout=wait_timeout,
298
+ )
299
+ return opened == "true"
300
+
301
+ def open_location_settings(self, wait_timeout: Optional[float] = 10) -> bool:
302
+ assert not self.page.web, "open_location_settings is not supported on web"
303
+ opened = self.invoke_method(
304
+ "open_location_settings",
305
+ wait_for_result=True,
306
+ wait_timeout=wait_timeout,
307
+ )
308
+ return opened == "true"
309
+
310
+ async def open_location_settings_async(
311
+ self, wait_timeout: Optional[float] = 10
312
+ ) -> bool:
313
+ assert not self.page.web, "open_location_settings is not supported on web"
314
+ opened = await self.invoke_method_async(
315
+ "open_location_settings",
316
+ wait_for_result=True,
317
+ wait_timeout=wait_timeout,
318
+ )
319
+ return opened == "true"
320
+
321
+ @property
322
+ def on_position_change(
323
+ self,
324
+ ) -> OptionalEventCallable[GeolocatorPositionChangeEvent]:
325
+ return self.__on_position_change.handler
326
+
327
+ @on_position_change.setter
328
+ def on_position_change(
329
+ self, handler: OptionalEventCallable[GeolocatorPositionChangeEvent]
330
+ ):
331
+ self.__on_position_change.handler = handler
332
+ self._set_attr("onPositionChange", True if handler is not None else None)
333
+
334
+ @property
335
+ def on_error(self) -> OptionalControlEventCallable:
336
+ return self._get_attr("error")
337
+
338
+ @on_error.setter
339
+ def on_error(self, handler: OptionalControlEventCallable):
340
+ self._add_event_handler("error", handler)