feat: add unified search integration
This commit is contained in:
parent
d6a9eb0c31
commit
c951a93b8c
@ -11,7 +11,7 @@ You need to have [GPodderSync](https://apps.nextcloud.com/apps/gpoddersync) inst
|
||||
- [x] Sync them with GPodderSync compatible clients
|
||||
- [ ] Import and export subscriptions
|
||||
- [x] Mobile friendly interface
|
||||
- [ ] Unified search integration
|
||||
- [x] Unified search integration
|
||||
- [x] Interface in multiple languages
|
||||
|
||||
## Screenshots
|
||||
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace OCA\RePod\AppInfo;
|
||||
|
||||
use OCA\RePod\Service\SearchProvider;
|
||||
use OCP\App\AppPathNotFoundException;
|
||||
use OCP\App\IAppManager;
|
||||
use OCP\AppFramework\App;
|
||||
@ -43,5 +44,7 @@ class Application extends App implements IBootstrap
|
||||
$initialState->provideInitialState('gpodder', $gpoddersync);
|
||||
}
|
||||
|
||||
public function register(IRegistrationContext $context): void {}
|
||||
public function register(IRegistrationContext $context): void {
|
||||
$context->registerSearchProvider(SearchProvider::class);
|
||||
}
|
||||
}
|
||||
|
@ -19,9 +19,9 @@ class EpisodesController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
IRequest $request,
|
||||
private IClientService $clientService,
|
||||
private EpisodeActionReader $episodeActionReader,
|
||||
private EpisodeActionRepository $episodeActionRepository,
|
||||
private IClientService $clientService,
|
||||
private UserService $userService
|
||||
) {
|
||||
parent::__construct(Application::APP_ID, $request);
|
||||
|
@ -14,7 +14,10 @@ use OCP\Util;
|
||||
|
||||
class PageController extends Controller
|
||||
{
|
||||
public function __construct(IRequest $request, private IConfig $config) {
|
||||
public function __construct(
|
||||
IRequest $request,
|
||||
private IConfig $config
|
||||
) {
|
||||
parent::__construct(Application::APP_ID, $request);
|
||||
}
|
||||
|
||||
|
@ -4,41 +4,22 @@ declare(strict_types=1);
|
||||
|
||||
namespace OCA\RePod\Controller;
|
||||
|
||||
use OCA\GPodderSync\Core\PodcastData\PodcastData;
|
||||
use OCA\RePod\AppInfo\Application;
|
||||
use OCA\RePod\Service\FyydService;
|
||||
use OCA\RePod\Service\ItunesService;
|
||||
use OCA\RePod\Service\MultiPodService;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http\JSONResponse;
|
||||
use OCP\IRequest;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class SearchController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
IRequest $request,
|
||||
private LoggerInterface $logger,
|
||||
private FyydService $fyydService,
|
||||
private ItunesService $itunesService
|
||||
private MultiPodService $multiPodService
|
||||
) {
|
||||
parent::__construct(Application::APP_ID, $request);
|
||||
}
|
||||
|
||||
public function index(string $value): JSONResponse {
|
||||
$podcasts = [];
|
||||
$providers = [$this->fyydService, $this->itunesService];
|
||||
|
||||
foreach ($providers as $provider) {
|
||||
try {
|
||||
$podcasts = [...$podcasts, ...$provider->search($value)];
|
||||
} catch (\Exception $e) {
|
||||
$this->logger->error($e->getMessage(), $e->getTrace());
|
||||
}
|
||||
}
|
||||
|
||||
usort($podcasts, fn (PodcastData $a, PodcastData $b) => $b->getFetchedAtUnix() <=> $a->getFetchedAtUnix());
|
||||
$podcasts = array_values(array_intersect_key($podcasts, array_unique(array_map(fn (PodcastData $feed) => $feed->getLink(), $podcasts))));
|
||||
|
||||
return new JSONResponse($podcasts);
|
||||
return new JSONResponse($this->multiPodService->search($value));
|
||||
}
|
||||
}
|
||||
|
@ -6,20 +6,16 @@ namespace OCA\RePod\Service;
|
||||
|
||||
use OCA\GPodderSync\Core\PodcastData\PodcastData;
|
||||
use OCP\Http\Client\IClientService;
|
||||
use OCP\IUserSession;
|
||||
use OCP\L10N\IFactory;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class FyydService implements IProvider
|
||||
class FyydService implements IPodProvider
|
||||
{
|
||||
private const BASE_URL = 'https://api.fyyd.de/0.2/';
|
||||
|
||||
public function __construct(
|
||||
private UserService $userService,
|
||||
private IClientService $clientService,
|
||||
private IFactory $l10n,
|
||||
private IUserSession $userSession,
|
||||
private LoggerInterface $logger
|
||||
private LoggerInterface $logger,
|
||||
private UserService $userService
|
||||
) {}
|
||||
|
||||
public function search(string $value): array {
|
||||
|
@ -6,7 +6,7 @@ namespace OCA\RePod\Service;
|
||||
|
||||
use OCA\GPodderSync\Core\PodcastData\PodcastData;
|
||||
|
||||
interface IProvider
|
||||
interface IPodProvider
|
||||
{
|
||||
/**
|
||||
* @return PodcastData[]
|
@ -7,7 +7,7 @@ namespace OCA\RePod\Service;
|
||||
use OCA\GPodderSync\Core\PodcastData\PodcastData;
|
||||
use OCP\Http\Client\IClientService;
|
||||
|
||||
class ItunesService implements IProvider
|
||||
class ItunesService implements IPodProvider
|
||||
{
|
||||
private const BASE_URL = 'https://itunes.apple.com/';
|
||||
|
||||
|
53
lib/Service/MultiPodService.php
Normal file
53
lib/Service/MultiPodService.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OCA\RePod\Service;
|
||||
|
||||
use OCA\GPodderSync\Core\PodcastData\PodcastData;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class MultiPodService implements IPodProvider
|
||||
{
|
||||
/**
|
||||
* @var IPodProvider[]
|
||||
*/
|
||||
private array $providers = [];
|
||||
|
||||
public function __construct(
|
||||
FyydService $fyydService,
|
||||
ItunesService $itunesService,
|
||||
private LoggerInterface $logger
|
||||
) {
|
||||
$this->providers = [$fyydService, $itunesService];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PodcastData[]
|
||||
*/
|
||||
public function search(string $value): array {
|
||||
$podcasts = [];
|
||||
|
||||
foreach ($this->providers as $provider) {
|
||||
try {
|
||||
$podcasts = [...$podcasts, ...$provider->search($value)];
|
||||
} catch (\Exception $e) {
|
||||
$this->logger->error($e->getMessage(), $e->getTrace());
|
||||
}
|
||||
}
|
||||
|
||||
usort($podcasts, fn (PodcastData $a, PodcastData $b) => $b->getFetchedAtUnix() <=> $a->getFetchedAtUnix());
|
||||
|
||||
return array_values(
|
||||
array_intersect_key(
|
||||
$podcasts,
|
||||
array_unique(
|
||||
array_map(
|
||||
fn (PodcastData $feed) => $feed->getLink(),
|
||||
array_filter($podcasts, fn (PodcastData $feed) => $feed->getLink())
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
65
lib/Service/SearchProvider.php
Normal file
65
lib/Service/SearchProvider.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OCA\RePod\Service;
|
||||
|
||||
use OCA\RePod\AppInfo\Application;
|
||||
use OCP\IL10N;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\IUser;
|
||||
use OCP\Search\IProvider;
|
||||
use OCP\Search\ISearchQuery;
|
||||
use OCP\Search\SearchResult;
|
||||
use OCP\Search\SearchResultEntry;
|
||||
|
||||
class SearchProvider implements IProvider
|
||||
{
|
||||
public function __construct(
|
||||
private IL10N $l10n,
|
||||
private IURLGenerator $urlGenerator,
|
||||
private MultiPodService $multiPodService
|
||||
) {}
|
||||
|
||||
public function getId(): string {
|
||||
return Application::APP_ID;
|
||||
}
|
||||
|
||||
public function getName(): string {
|
||||
return $this->l10n->t('Podcasts');
|
||||
}
|
||||
|
||||
public function getOrder(string $route, array $routeParameters): ?int {
|
||||
if (0 === strpos($route, Application::APP_ID.'.')) {
|
||||
// Active app, prefer my results
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 25;
|
||||
}
|
||||
|
||||
public function search(IUser $user, ISearchQuery $query): SearchResult {
|
||||
$podcasts = $this->multiPodService->search($query->getTerm());
|
||||
|
||||
$searchResults = [];
|
||||
foreach ($podcasts as $podcast) {
|
||||
$title = $podcast->getTitle();
|
||||
$link = $podcast->getLink();
|
||||
|
||||
if ($title && $link) {
|
||||
$searchResults[] = new SearchResultEntry(
|
||||
$podcast->getImageUrl() ?? $this->urlGenerator->linkTo(Application::APP_ID, 'img/app.svg'),
|
||||
$title,
|
||||
$podcast->getAuthor() ?? '',
|
||||
$this->urlGenerator->linkToRoute('repod.page.index').'/#/'.urlencode(base64_encode($link)),
|
||||
$this->urlGenerator->linkTo(Application::APP_ID, 'img/app.svg')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return SearchResult::complete(
|
||||
$this->l10n->t('Podcasts'),
|
||||
$searchResults
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user