Skip to content

Commit 0c6b98d

Browse files
committed
feat: show version on web page
1 parent 8dd3954 commit 0c6b98d

File tree

14 files changed

+212
-98
lines changed

14 files changed

+212
-98
lines changed

DEVELOP.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11

2-
This project is developed using FastAPI, Vue, and Element-UI. It starts the service locally and displays the UI hierarchy tree through a web browser.
3-
4-
**Tech Stack**
2+
# Tech Stack
53

64
- python3
75
- html/css/js
@@ -21,7 +19,7 @@ poetry install
2119
poetry build
2220
```
2321

24-
## Run
22+
# Run
2523
```
2624
poetry run python3 -m uiviewer
2725
```

README.md

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,52 @@
11
# ui-viewer
2+
[![github actions](https://github.com/codematrixer/ui-viewer/actions/workflows/release.yml/badge.svg)](https://github.com/codematrixer/ui-viewer/actions)
3+
[![pypi version](https://img.shields.io/pypi/v/uiviewer.svg)](https://pypi.python.org/pypi/uiviewer)
4+
![python](https://img.shields.io/pypi/pyversions/uiviewer.svg)
5+
26
UI hierarchy visualization tool, supporting Android, iOS, HarmonyOS NEXT.
37

4-
![showcase](./docs/imgs/show.gif)
8+
This project is developed using FastAPI and Vue. It starts the service locally and displays UI hierarchy tree through web browser.
9+
10+
![show](https://i.ibb.co/Phfm9Q1/show.gif)
511

612
# Installation
13+
- python3.8+
14+
715
```shell
816
pip3 install -U uiviewer
917
```
1018

1119
# Run
12-
Start with a default port (8000)
20+
Run the following command on the terminal. (default port `8000`)
21+
1322
```shell
1423
uiviewer
1524
# or
1625
python3 -m uiviewer
26+
27+
INFO: Started server process [46814]
28+
INFO: Waiting for application startup.
29+
INFO: Application startup complete.
30+
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
31+
INFO: 127.0.0.1:55080 - "GET / HTTP/1.1" 307 Temporary Redirect
32+
INFO: 127.0.0.1:55080 - "GET /static/index.html HTTP/1.1" 200 OK
33+
INFO: 127.0.0.1:55080 - "GET /static/css/style.css HTTP/1.1" 200 OK
34+
INFO: 127.0.0.1:55080 - "GET /static/js/index.js HTTP/1.1" 200 OK
35+
INFO: 127.0.0.1:55080 - "GET /static/js/api.js HTTP/1.1" 200 OK
36+
INFO: 127.0.0.1:55082 - "GET /static/js/utils.js HTTP/1.1" 200 OK
37+
INFO: 127.0.0.1:55082 - "GET /static/js/config.js HTTP/1.1" 200 OK
38+
INFO: 127.0.0.1:55082 - "GET /version HTTP/1.1" 200 OK
1739
```
18-
Start with a custom port
19-
```
40+
And then open the browser to [http://localhost:8000](http://localhost:8000)
41+
42+
You can also customize port to start the service.
43+
```shell
2044
uiviewer -p <PORT>
45+
# or
2146
python3 -m uiviewer -p <PORT>
2247

2348
```
24-
and then open the browser to [http://localhost:8000](http://localhost:8000)
49+
2550

2651

2752
# Tips
@@ -33,17 +58,40 @@ and then open the browser to [http://localhost:8000](http://localhost:8000)
3358
```
3459
- Second, Use `tidevice` or `iproxy` to forward the wda port,and keep it running.
3560
```
36-
tidevice relay <local_port> 8100
61+
tidevice relay 8100 8100
62+
```
63+
- And then, To ensure the success of the browser to access `http://localhost:8100/status`, return like this:
64+
```
65+
{
66+
"value": {
67+
"build": {
68+
"productBundleIdentifier": "com.facebook.WebDriverAgentRunner",
69+
"time": "Mar 25 2024 15:17:30"
70+
},
71+
...
72+
"state": "success",
73+
"ready": true
74+
},
75+
"sessionId": null
76+
}
3777
```
38-
- Finally, To ensure the success of the browser to access `http://localhost:<local_port>/status`
78+
- Finally, Input the **`wdaUrl`** in the web page, such as `http://localhost:8100`
79+
3980
- On iOS,WDA can easily freeze when dumping high UI hierarchy. You can reduce the **`maxDepth`** on the web page. The default is 30.
4081

41-
# preview
82+
# Preview
4283
- HarmonyOS
43-
![harmony](./docs/imgs/harmony.png)
84+
![harmony](https://i.ibb.co/82BrJ1H/harmony.png)
4485

4586
- Android
46-
![android](./docs/imgs/android.png)
87+
![android](https://i.ibb.co/RySs497/android.png)
4788

4889
- iOS
49-
![ios](./docs/imgs/ios.png)
90+
![ios](https://i.ibb.co/VVWtTS3/ios.png)
91+
92+
93+
# Relevant
94+
- https://github.com/codematrixer/hmdriver2
95+
- https://github.com/openatx/uiautomator2
96+
- https://github.com/openatx/facebook-wda
97+
- https://github.com/alibaba/web-editor

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "uiviewer"
3-
version = "1.0.0"
3+
version = "1.0.1"
44
description = "UI hierarchy visualization tool, supporting Android, iOS, HarmonyOS NEXT."
55
authors = ["codematrixer <[email protected]>"]
66
license = "MIT"

uiviewer/__init__.py

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1 @@
1-
# -*- coding: utf-8 -*-
2-
3-
import logging
4-
5-
formatter = logging.Formatter('[%(asctime)s] %(filename)15s[line:%(lineno)4d] \
6-
[%(levelname)s] %(message)s',
7-
datefmt='%Y-%m-%d %H:%M:%S')
8-
9-
logger = logging.getLogger('hmdriver2')
10-
logger.setLevel(logging.DEBUG)
11-
12-
console_handler = logging.StreamHandler()
13-
console_handler.setLevel(logging.DEBUG)
14-
console_handler.setFormatter(formatter)
15-
16-
logger.addHandler(console_handler)
17-
18-
19-
__all__ = ['logger']
1+
# -*- coding: utf-8 -*-

uiviewer/__main__.py

Lines changed: 6 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,12 @@
44
import webbrowser
55
import uvicorn
66
import threading
7-
from typing import Union, Optional
87

9-
from fastapi import FastAPI, Request, Query, HTTPException
8+
from fastapi import FastAPI, Request, HTTPException
109
from fastapi.staticfiles import StaticFiles
11-
from fastapi.responses import JSONResponse, RedirectResponse
12-
13-
from uiviewer._device import (
14-
list_serials,
15-
init_device,
16-
cached_devices,
17-
AndroidDevice,
18-
IosDevice,
19-
HarmonyDevice
20-
)
10+
from fastapi.responses import JSONResponse
11+
12+
from uiviewer.routers import api
2113
from uiviewer._models import ApiResponse
2214

2315

@@ -29,6 +21,8 @@
2921

3022
app.mount("/static", StaticFiles(directory=static_dir), name="static")
3123

24+
app.include_router(api.router)
25+
3226

3327
@app.exception_handler(Exception)
3428
def global_exception_handler(request: Request, exc: Exception):
@@ -50,42 +44,6 @@ def open_browser(port):
5044
webbrowser.open_new(f"http://127.0.0.1:{port}")
5145

5246

53-
@app.get("/")
54-
def root():
55-
return RedirectResponse(url="/static/index.html")
56-
57-
58-
@app.get("/health")
59-
def health():
60-
return "ok"
61-
62-
63-
@app.get("/{platform}/serials", response_model=ApiResponse)
64-
def get_serials(platform: str):
65-
serials = list_serials(platform)
66-
return ApiResponse.doSuccess(serials)
67-
68-
69-
@app.post("/{platform}/{serial}/connect", response_model=ApiResponse)
70-
def connect(platform: str, serial: str, wdaUrl: Optional[str] = Query(None), maxDepth: Optional[int] = Query(None)):
71-
ret = init_device(platform, serial, wdaUrl, maxDepth)
72-
return ApiResponse.doSuccess(ret)
73-
74-
75-
@app.get("/{platform}/{serial}/screenshot", response_model=ApiResponse)
76-
def screenshot(platform: str, serial: str):
77-
device: Union[AndroidDevice, IosDevice, HarmonyDevice] = cached_devices.get((platform, serial))
78-
data = device.take_screenshot()
79-
return ApiResponse.doSuccess(data)
80-
81-
82-
@app.get("/{platform}/{serial}/hierarchy", response_model=ApiResponse)
83-
def dump_hierarchy(platform: str, serial: str):
84-
device: Union[AndroidDevice, IosDevice, HarmonyDevice] = cached_devices.get((platform, serial))
85-
data = device.dump_hierarchy()
86-
return ApiResponse.doSuccess(data)
87-
88-
8947
def run(port=8000):
9048
timer = threading.Timer(1.0, open_browser, args=[port])
9149
timer.daemon = True

uiviewer/_device.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import abc
44
import tempfile
5-
from typing import List, Dict, Union, Tuple
5+
from typing import List, Dict, Union, Tuple, Optional
66
from functools import cached_property # python3.8+
77

88
from PIL import Image
@@ -101,9 +101,13 @@ class IosDevice(DeviceMeta):
101101
def __init__(self, udid: str, wda_url: str, max_depth: int) -> None:
102102
self.udid = udid
103103
self.wda_url = wda_url
104-
self.max_depth = max_depth
104+
self._max_depth = max_depth
105105
self.client = wda.Client(wda_url)
106106

107+
@property
108+
def max_depth(self) -> int:
109+
return int(self._max_depth) if self._max_depth else 30
110+
107111
@cached_property
108112
def scale(self) -> int:
109113
return self.client.scale
@@ -152,7 +156,7 @@ def get_device(platform: str, serial: str, wda_url: str, max_depth: int) -> Unio
152156
cached_devices = {}
153157

154158

155-
def init_device(platform: str, serial: str, wda_url: str = None, max_depth: int = 30) -> bool:
159+
def init_device(platform: str, serial: str, wda_url: str, max_depth: int):
156160

157161
if serial not in list_serials(platform):
158162
raise HTTPException(status_code=500, detail=f"Device<{serial}> not found")

uiviewer/_error.py

Lines changed: 0 additions & 4 deletions
This file was deleted.

uiviewer/_logger.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# -*- coding: utf-8 -*-
2+
3+
import logging
4+
5+
formatter = logging.Formatter('[%(asctime)s] %(filename)15s[line:%(lineno)4d] \
6+
[%(levelname)s] %(message)s',
7+
datefmt='%Y-%m-%d %H:%M:%S')
8+
9+
logger = logging.getLogger('hmdriver2')
10+
logger.setLevel(logging.DEBUG)
11+
12+
console_handler = logging.StreamHandler()
13+
console_handler.setLevel(logging.DEBUG)
14+
console_handler.setFormatter(formatter)
15+
16+
logger.addHandler(console_handler)
17+
18+
19+
__all__ = ['logger']

uiviewer/_version.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# -*- coding: utf-8 -*-
2+
3+
import importlib.metadata
4+
5+
__version__ = importlib.metadata.version('uiviewer')

uiviewer/routers/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# -*- coding: utf-8 -*-

0 commit comments

Comments
 (0)