diff --git a/ServiceAPI/Search.php b/ServiceAPI/Search.php new file mode 100644 index 00000000..46def4f4 --- /dev/null +++ b/ServiceAPI/Search.php @@ -0,0 +1,76 @@ +user = $user; + $this->users = new Users; + $this->clubs = new Clubs; + $this->videos = new Videos; + } + + function fastSearch(string $query, string $type = "users", callable $resolve, callable $reject) + { + if($query == "" || strlen($query) < 3) + $reject(12, "No input or input < 3"); + + $repo; + $sort; + + switch($type) { + default: + case "users": + $repo = (new Users); + $sort = "rating DESC"; + + break; + case "groups": + $repo = (new Clubs); + $sort = "id ASC"; + + break; + case "videos": + $repo = (new Videos); + $sort = "created ASC"; + + break; + } + + $res = $repo->find($query, ["doNotSearchMe" => $this->user->getId()], $sort); + + $results = array_slice(iterator_to_array($res), 0, 5); + + $count = sizeof($results); + + $arr = [ + "count" => $count, + "items" => [] + ]; + + if(sizeof($results) < 1) { + $reject(2, "No results"); + } + + foreach($results as $res) { + $arr["items"][] = [ + "id" => $res->getId(), + "name" => $type == "users" ? $res->getCanonicalName() : $res->getName(), + "avatar" => $type != "videos" ? $res->getAvatarUrl() : $res->getThumbnailURL(), + "url" => $type != "videos" ? $res->getUrl() : "/video".$res->getPrettyId(), + "description" => ovk_proc_strtr($res->getDescription() ?? "...", 40) + ]; + } + + $resolve($arr); + } +} diff --git a/Web/Models/Repositories/Users.php b/Web/Models/Repositories/Users.php index 0eec3306..6c165aa3 100644 --- a/Web/Models/Repositories/Users.php +++ b/Web/Models/Repositories/Users.php @@ -58,7 +58,7 @@ class Users $nnparamsCount = 0; foreach($pars as $paramName => $paramValue) - if($paramName != "before" && $paramName != "after" && $paramName != "gender" && $paramName != "maritalstatus" && $paramName != "politViews") + if($paramName != "before" && $paramName != "after" && $paramName != "gender" && $paramName != "maritalstatus" && $paramName != "politViews" && $paramName != "doNotSearchMe") $paramValue != NULL ? $notNullParams += ["$paramName" => "%$paramValue%"] : NULL; else $paramValue != NULL ? $notNullParams += ["$paramName" => "$paramValue"] : NULL; @@ -125,6 +125,9 @@ class Users case "gender": $result->where("sex ?", $paramValue); break; + case "doNotSearchMe": + $result->where("id !=", $paramValue); + break; } } } diff --git a/Web/Presenters/templates/@layout.xml b/Web/Presenters/templates/@layout.xml index 7bb7e194..cd23d47a 100644 --- a/Web/Presenters/templates/@layout.xml +++ b/Web/Presenters/templates/@layout.xml @@ -93,8 +93,8 @@ {if !$atSearch}
- - +
+ {else}
diff --git a/Web/static/css/main.css b/Web/static/css/main.css index ac8de971..bef99acf 100644 --- a/Web/static/css/main.css +++ b/Web/static/css/main.css @@ -2487,3 +2487,49 @@ a.poll-retract-vote { .page_content.overscrolled div[class$="_big_block"] { width: 100%; } + +.searchTips +{ + position: absolute; + background: white; + padding-left: 6px; + padding-right: 6px; + padding-bottom: 6px; + border: 1px solid #C0CAD5; + border-top: 0px; + width: fit-content; + z-index: 666666; + margin-top: -2px; +} + +.searchTips td +{ + color: black; + padding: 3px; + font-weight: lighter; + position:relative; +} + +.searchTips td .desq +{ + margin-top: -9px; +} + +.restip td a:hover +{ + color: black; + font-weight: lighter; + text-decoration: none; +} + +.searchTips .restip +{ + padding-right: 10px; + cursor: pointer; + user-select: none; +} + +.searchTips .restip:hover +{ + background: rgb(236, 235, 235); +} diff --git a/Web/static/js/openvk.cls.js b/Web/static/js/openvk.cls.js index 31b7aa5d..22144cfc 100644 --- a/Web/static/js/openvk.cls.js +++ b/Web/static/js/openvk.cls.js @@ -590,9 +590,11 @@ async function decreaseSearch() { // чтобы люди успели выбрать что искать и поиск не скрывался сразу await new Promise(r => setTimeout(r, 4000)); + // console.log("search decreased") - if(document.activeElement !== searchInput) + if(document.activeElement !== searchInput && document.activeElement !== typer) { + srcht.setAttribute("hidden", "hidden") document.getElementById("searchInput").style.background = "url('/assets/packages/static/openvk/img/search_icon.png') no-repeat 3px 4px"; document.getElementById("searchInput").style.backgroundColor = "#fff"; document.getElementById("searchInput").style.paddingLeft = "18px"; @@ -642,6 +644,43 @@ function resetSearch() } } +async function checkSearchTips() +{ + let query = searchInput.value; + + await new Promise(r => setTimeout(r, 1000)); + + let type = typer.value; + let smt = type == "users" || type == "groups" || type == "videos"; + + if(query.length > 3 && query == searchInput.value && smt) { + srcht.removeAttribute("hidden") + let etype = type + + try { + let results = await API.Search.fastSearch(escapeHtml(query), etype) + + srchrr.innerHTML = "" + + for(const el of results["items"]) { + srchrr.insertAdjacentHTML("beforeend", ` + + + + + +

${escapeHtml(el.name)}

+

${escapeHtml(el.description)}

+ + + `) + } + } catch(rejection) { + srchrr.innerHTML = tr("no_results") + } + } +} + $(document).on("scroll", () => { if($(document).scrollTop() > $(".sidebar").height() + 50) { $(".floating_sidebar")[0].classList.add("show"); diff --git a/locales/en.strings b/locales/en.strings index 0000e4b2..72bf67f8 100644 --- a/locales/en.strings +++ b/locales/en.strings @@ -1507,6 +1507,8 @@ "closed_group_post" = "This is a post from private group"; "deleted_target_comment" = "This comment belongs to deleted post"; +"no_results" = "No results"; + /* Mobile */ "mobile_friends" = "Friends"; "mobile_photos" = "Photos"; diff --git a/locales/ru.strings b/locales/ru.strings index 971afd30..ce943e33 100644 --- a/locales/ru.strings +++ b/locales/ru.strings @@ -1400,6 +1400,8 @@ "closed_group_post" = "Эта запись из закрытой группы"; "deleted_target_comment" = "Этот комментарий принадлежит к удалённой записи"; +"no_results" = "Результатов нет"; + /* Mobile */ "mobile_friends" = "Друзья"; "mobile_photos" = "Фотографии";