Skip to content

Commit

Permalink
Add mobile apps listing to backend
Browse files Browse the repository at this point in the history
  • Loading branch information
razzeee committed Jan 9, 2025
1 parent b175296 commit 7eb1990
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 1 deletion.
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

0 comments on commit 7eb1990

Please sign in to comment.