Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add mobile apps listing to backend #4427

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions backend/app/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,24 @@ def get_verified(
return result


@router.get("/collection/mobile", tags=["app"])
def get_mobile(
page: int | None = None,
per_page: int | None = None,
locale: str = "en",
response: Response = Response(),
):
if (page is None and per_page is not None) or (
page is not None and per_page is None
):
response.status_code = 400
return response

result = search.get_by_mobile(page, per_page, locale)

return result


@router.get("/popular/last-month", tags=["app"])
def get_popular_last_month(
page: int | None = None,
Expand Down
1 change: 1 addition & 0 deletions backend/app/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ def add_to_search(app_id: str, app: dict, apps_locale: dict) -> dict:
"id": utils.get_clean_app_id(app_id),
"type": type,
"name": app["name"],
"isMobileFriendly": app.get("isMobileFriendly", False),
"summary": app["summary"],
"translations": translations,
"keywords": search_keywords,
Expand Down
20 changes: 20 additions & 0 deletions backend/app/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class SearchQuery(BaseModel):
"arches",
"icon",
"keywords",
"isMobileFriendly",
]
)

Expand Down Expand Up @@ -240,6 +241,25 @@ def get_by_verified(page: int | None, hits_per_page: int | None, locale: str):
)


def get_by_mobile(page: int | None, hits_per_page: int | None, locale: str):
return _translate_name_and_summary(
locale,
client.index("apps").search(
"",
{
"filter": [
"isMobileFriendly = true",
"type IN [console-application, desktop-application]",
"NOT icon IS NULL",
],
"sort": ["trending:desc"],
"hitsPerPage": hits_per_page or 250,
"page": page or 1,
},
),
)


def get_by_developer(
developer: str, page: int | None, hits_per_page: int | None, locale: str
):
Expand Down
60 changes: 59 additions & 1 deletion backend/app/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import os
import re
from datetime import datetime, timedelta
from typing import Any
from typing import Any, Literal

import gi
import jwt
Expand All @@ -21,6 +21,9 @@
clean_id_re = re.compile("[^a-zA-Z0-9_-]+")
remove_desktop_re = re.compile(r"\.desktop$")

mobile_min_size = 360
mobile_max_size = 768


class Hasher:
"""
Expand Down Expand Up @@ -96,6 +99,46 @@ def appstream2dict(appstream_url=None) -> dict[str, dict]:
app["type"] = component.attrib.get("type", "generic")
app["locales"] = {}

isMobileFriendly: list[bool] = []
requires = component.find("requires")
if requires is not None:
if display_lengths := requires.findall("display_length"):
for display_length in display_lengths:
compare: Literal[
"eq",
"ne",
"lt",
"gt",
"le",
"ge",
] = display_length.attrib.get("compare") or "ge"

isMobileFriendly.append(
compare_requires_is_between_mobile_target(
int(display_length.text),
compare,
)
)

hasTouch = False
supports = component.find("supports")
if supports is not None:
if controls := supports.findall("control"):
for control in controls:
if control.text == "touch":
hasTouch = True

recommends = component.find("recommends")
if recommends is not None:
if controls := recommends.findall("control"):
for control in controls:
if control.text == "touch":
hasTouch = True

app["isMobileFriendly"] = (
all(isMobileFriendly) and any(isMobileFriendly) and hasTouch
)

descriptions = component.findall("description")
if len(descriptions):
for desc in descriptions:
Expand Down Expand Up @@ -429,6 +472,21 @@ def appstream2dict(appstream_url=None) -> dict[str, dict]:
return apps


def compare_requires_is_between_mobile_target(
display_length: int,
compare: Literal["ge", "lt", "gt", "le", "eq", "ne"],
):
if compare == "ge" and display_length <= mobile_max_size:
return True
if compare == "lt" and display_length > mobile_max_size:
return True
if compare == "gt" and display_length < mobile_min_size:
return True
if compare == "le" and display_length >= mobile_min_size:
return True
return False


def get_clean_app_id(app_id: str):
return re.sub(clean_id_re, "_", app_id)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,8 @@
"is_free_license": true,
"app_id": "org.sugarlabs.Maze",
"icon": "https://dl.flathub.org/repo/appstream/x86_64/icons/128x128/org.sugarlabs.Maze.png",
"categories": [
"Game"
],
"main_categories": [
"Game"
],
"categories": ["Game"],
"main_categories": ["Game"],
"sub_categories": [],
"developer_name": "Sugar Labs Community",
"verification_verified": false,
Expand All @@ -34,12 +30,11 @@
"verification_timestamp": null,
"runtime": "org.gnome.Platform/x86_64/3.36",
"updated_at": 1610973680,
"arches": [
"x86_64"
],
"arches": ["x86_64"],
"added_at": 1610973680,
"trending": 5.0,
"installs_last_month": 567
"installs_last_month": 567,
"isMobileFriendly": false
}
],
"query": "",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,8 @@
"is_free_license": true,
"app_id": "org.sugarlabs.Maze",
"icon": "https://dl.flathub.org/repo/appstream/x86_64/icons/128x128/org.sugarlabs.Maze.png",
"categories": [
"Game"
],
"main_categories": [
"Game"
],
"categories": ["Game"],
"main_categories": ["Game"],
"sub_categories": [],
"developer_name": "Sugar Labs Community",
"verification_verified": false,
Expand All @@ -28,12 +24,11 @@
"verification_timestamp": null,
"runtime": "org.gnome.Platform/x86_64/3.36",
"updated_at": 1610973680,
"arches": [
"x86_64"
],
"arches": ["x86_64"],
"added_at": 1610973680,
"trending": 5.0,
"installs_last_month": 567
"installs_last_month": 567,
"isMobileFriendly": false
}
],
"query": "",
Expand All @@ -42,4 +37,4 @@
"page": 1,
"totalPages": 1,
"totalHits": 1
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,8 @@
"is_free_license": true,
"app_id": "org.sugarlabs.Maze",
"icon": "https://dl.flathub.org/repo/appstream/x86_64/icons/128x128/org.sugarlabs.Maze.png",
"categories": [
"Game"
],
"main_categories": [
"Game"
],
"categories": ["Game"],
"main_categories": ["Game"],
"sub_categories": [],
"developer_name": "Sugar Labs Community",
"verification_verified": false,
Expand All @@ -34,12 +30,11 @@
"verification_timestamp": null,
"runtime": "org.gnome.Platform/x86_64/3.36",
"updated_at": 1610973680,
"arches": [
"x86_64"
],
"arches": ["x86_64"],
"added_at": 1610973680,
"trending": 5.0,
"installs_last_month": 567
"installs_last_month": 567,
"isMobileFriendly": false
}
],
"query": "",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,8 @@
"is_free_license": true,
"app_id": "org.sugarlabs.Maze",
"icon": "https://dl.flathub.org/repo/appstream/x86_64/icons/128x128/org.sugarlabs.Maze.png",
"categories": [
"Game"
],
"main_categories": [
"Game"
],
"categories": ["Game"],
"main_categories": ["Game"],
"sub_categories": [],
"developer_name": "Sugar Labs Community",
"verification_verified": false,
Expand All @@ -28,12 +24,11 @@
"verification_timestamp": null,
"runtime": "org.gnome.Platform/x86_64/3.36",
"updated_at": 1610973680,
"arches": [
"x86_64"
],
"arches": ["x86_64"],
"added_at": 1610973680,
"trending": 5.0,
"installs_last_month": 567
"installs_last_month": 567,
"isMobileFriendly": false
}
],
"query": "",
Expand All @@ -42,4 +37,4 @@
"page": 1,
"totalPages": 1,
"totalHits": 1
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,8 @@
"name": "Maze",
"summary": "A simple maze game",
"developer_name": "Sugar Labs Community",
"categories": [
"Game"
],
"kudos": [
"HiDpiIcon"
],
"categories": ["Game"],
"kudos": ["HiDpiIcon"],
"project_license": "GPL-3.0-or-later",
"launchable": {
"value": "org.sugarlabs.Maze.desktop",
Expand Down Expand Up @@ -392,5 +388,6 @@
"runtime": "org.gnome.Platform/x86_64/3.36",
"sdk": "org.gnome.Sdk/x86_64/3.36"
},
"is_free_license": true
}
"is_free_license": true,
"isMobileFriendly": false
}
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,8 @@
"name": "Maze",
"summary": "A simple maze game",
"developer_name": "Sugar Labs Community",
"categories": [
"Game"
],
"kudos": [
"HiDpiIcon"
],
"categories": ["Game"],
"kudos": ["HiDpiIcon"],
"project_license": "GPL-3.0-or-later",
"launchable": {
"value": "org.sugarlabs.Maze.desktop",
Expand Down Expand Up @@ -392,5 +388,6 @@
"runtime": "org.gnome.Platform/x86_64/3.36",
"sdk": "org.gnome.Sdk/x86_64/3.36"
},
"is_free_license": true
}
"is_free_license": true,
"isMobileFriendly": false
}
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,8 @@
"name": "Maze",
"summary": "Ein simples Irrgartenspiel",
"developer_name": "Sugar Labs Community",
"categories": [
"Game"
],
"kudos": [
"HiDpiIcon"
],
"categories": ["Game"],
"kudos": ["HiDpiIcon"],
"project_license": "GPL-3.0-or-later",
"launchable": {
"value": "org.sugarlabs.Maze.desktop",
Expand Down Expand Up @@ -392,5 +388,6 @@
"runtime": "org.gnome.Platform/x86_64/3.36",
"sdk": "org.gnome.Sdk/x86_64/3.36"
},
"is_free_license": true
}
"is_free_license": true,
"isMobileFriendly": false
}
Loading
Loading