Compare commits
37 Commits
Author | SHA1 | Date | |
---|---|---|---|
86276dcfcc | |||
|
aa043623f6 | ||
4a82022cf0 | |||
879bd15f1d | |||
592e6b6b68 | |||
c332dcd986 | |||
28be29efae | |||
9c4db19b59 | |||
38e44b9731 | |||
26802b49a5 | |||
d7dfb25062 | |||
99977b1db4 | |||
230b646ceb | |||
06acea519c | |||
f5c8689d50 | |||
e99b2c972d | |||
40ecea63d2 | |||
e43adc79a1 | |||
eb6a4b2d9b | |||
1d8ea08798 | |||
7e6536c7ee | |||
|
c1a6d29362 | ||
13969d5c03 | |||
|
ebf8b501e5 | ||
e368baa0ee | |||
a90fcceb7b | |||
6c0976bc16 | |||
c439f8585e | |||
d4e936b077 | |||
|
ea8514016f | ||
c8fa87d03d | |||
b7e114f131 | |||
a3879021e4 | |||
07fd241b2a | |||
52bedda53d | |||
f98cc71d60 | |||
25af5bdf54 |
@ -55,7 +55,7 @@ jobs:
|
||||
- uses: akkuman/gitea-release-action@v1
|
||||
with:
|
||||
files: |
|
||||
build/artifacts/repod.tar.gz
|
||||
build/artifacts/${{ gitea.event.repository.name }}.tar.gz
|
||||
- uses: FKLC/sign-files-action@v1.0.0
|
||||
with:
|
||||
privateKey: ${{ secrets.PRIVATEKEY }}
|
||||
@ -63,13 +63,13 @@ jobs:
|
||||
extension: .sig
|
||||
outputFolder: build/artifacts
|
||||
files: |
|
||||
build/artifacts/repod.tar.gz
|
||||
build/artifacts/${{ gitea.event.repository.name }}.tar.gz
|
||||
- id: sign
|
||||
run: echo "SIGNATURE=$(cat build/artifacts/repod.tar.gz.sig | openssl base64 -A)" >> $GITHUB_OUTPUT
|
||||
run: echo "SIGNATURE=$(cat build/artifacts/${{ gitea.event.repository.name }}.tar.gz.sig | openssl base64 -A)" >> $GITHUB_OUTPUT
|
||||
- uses: actionsflow/axios@v1
|
||||
with:
|
||||
url: https://apps.nextcloud.com/api/v1/apps/releases
|
||||
method: POST
|
||||
accept: 200,201
|
||||
headers: '{ "Authorization": "Token <<<${{ secrets.TOKEN }}>>>" }'
|
||||
data: '{ "download": "https://git.crystalyx.net/Xefir/repod/releases/download/<<<${{ gitea.ref_name }}>>>/repod.tar.gz", "signature": "<<<${{ steps.sign.outputs.SIGNATURE }}>>>" }'
|
||||
data: '{ "download": "https://git.crystalyx.net/${{ gitea.repository }}/releases/download/<<<${{ gitea.ref_name }}>>>/${{ gitea.event.repository.name }}.tar.gz", "signature": "<<<${{ steps.sign.outputs.SIGNATURE }}>>>" }'
|
||||
|
@ -13,7 +13,6 @@ class MyConfig extends Config
|
||||
$rules = parent::getRules();
|
||||
$rules['@PhpCsFixer'] = true;
|
||||
$rules['curly_braces_position']['classes_opening_brace'] = 'next_line_unless_newline_at_signature_end';
|
||||
$rules['phpdoc_separation'] = false;
|
||||
$rules['phpdoc_to_comment'] = false;
|
||||
return $rules;
|
||||
}
|
||||
|
10
CHANGELOG.md
10
CHANGELOG.md
@ -1,3 +1,13 @@
|
||||
## 3.4.1 - Skip & Chill - 2024-11-12
|
||||
|
||||
### Changed
|
||||
- 💄 Make a little gap between player's controls
|
||||
|
||||
### Fixed
|
||||
- 📝 Descriptions are now well formatted
|
||||
- ⏩ Chapters supported !
|
||||
> Click on a timestamp in descriptions to skip to the specified part of the podcast
|
||||
|
||||
## 3.4.0 - Good Night - 2024-11-09
|
||||
|
||||
### Added
|
||||
|
45
Makefile
45
Makefile
@ -1,39 +1,4 @@
|
||||
# https://github.com/nextcloud/appstore/blob/fixed-templates/nextcloudappstore/scaffolding/app-templates/26/app/Makefile
|
||||
# Generic Makefile for building and packaging a Nextcloud app which uses npm and
|
||||
# Composer.
|
||||
#
|
||||
# Dependencies:
|
||||
# * make
|
||||
# * which
|
||||
# * curl: used if phpunit and composer are not installed to fetch them from the web
|
||||
# * tar: for building the archive
|
||||
# * npm: for building and testing everything JS
|
||||
#
|
||||
# If no composer.json is in the app root directory, the Composer step
|
||||
# will be skipped. The same goes for the package.json which can be located in
|
||||
# the app root or the js/ directory.
|
||||
#
|
||||
# The npm command by launches the npm build script:
|
||||
#
|
||||
# npm run build
|
||||
#
|
||||
# The npm test command launches the npm test script:
|
||||
#
|
||||
# npm run test
|
||||
#
|
||||
# The idea behind this is to be completely testing and build tool agnostic. All
|
||||
# build tools and additional package managers should be installed locally in
|
||||
# your project, since this won't pollute people's global namespace.
|
||||
#
|
||||
# The following npm scripts in your package.json install and update the bower
|
||||
# and npm dependencies and use gulp as build system (notice how everything is
|
||||
# run from the node_modules folder):
|
||||
#
|
||||
# "scripts": {
|
||||
# "test": "node node_modules/gulp-cli/bin/gulp.js karma",
|
||||
# "prebuild": "npm install && node_modules/bower/bin/bower install && node_modules/bower/bin/bower update",
|
||||
# "build": "node node_modules/gulp-cli/bin/gulp.js"
|
||||
# },
|
||||
|
||||
app_name=$(notdir $(CURDIR))
|
||||
build_tools_directory=$(CURDIR)/build/tools
|
||||
@ -159,11 +124,11 @@ appstore:
|
||||
# Start a nextcloud server on Docker to kickstart developement
|
||||
.PHONY: dev
|
||||
dev: build
|
||||
docker stop repod || true
|
||||
docker rm repod || true
|
||||
docker build -t repod .
|
||||
docker run -itd --rm --name repod -v $(CURDIR):/var/www/html/apps/repod -p 80:80 repod
|
||||
npm run watch
|
||||
docker stop $(app_name) || true
|
||||
docker rm $(app_name) || true
|
||||
docker build -t $(app_name) .
|
||||
docker run -itd --rm --name $(app_name) -v $(CURDIR):/var/www/html/apps/$(app_name) -p 80:80 $(app_name)
|
||||
npm run watch || docker stop $(app_name)
|
||||
|
||||
# Generate translations
|
||||
.PHONY: l10n
|
||||
|
55
README.md
55
README.md
@ -6,12 +6,12 @@ You need to have [GPodderSync](https://apps.nextcloud.com/apps/gpoddersync) inst
|
||||
|
||||
## Features
|
||||
|
||||
- Browse podcasts and play them directly in Nextcloud
|
||||
- Keep track of subscribed shows and episodes
|
||||
- Sync them with GPodderSync compatible clients
|
||||
- Import and export subscriptions
|
||||
- Mobile friendly interface
|
||||
- Unified search integration
|
||||
- 🔍 Browse and subscribe huge collection of podcasts
|
||||
- 🔊 Listen to episodes directly in Nextcloud
|
||||
- 📋 Keep track of subscribed shows and episodes
|
||||
- 🌐 Sync them with GPodderSync compatible clients
|
||||
- 📱 Mobile friendly interface
|
||||
- 📡 Import and export your subscriptions
|
||||
|
||||
## Comparaison with similar apps for Nextcloud
|
||||
|
||||
@ -19,37 +19,32 @@ You need to have [GPodderSync](https://apps.nextcloud.com/apps/gpoddersync) inst
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Actively maintened | ✅ | ✅ | ✅ | ❌ |
|
||||
| Play your local music files | ❌ | ❌ | ✅ | ❌ |
|
||||
| Sync with [GPodder clients](#clients-supporting-sync-of-gpoddersync) | ✅ | ✅ | ❌ | ❌ |
|
||||
| Sync with [GPodder clients](#clients-supporting-sync-of-gpoddersync) | ✅ | ✅ | [⭕](https://github.com/owncloud/music/issues/975) | [⭕](https://git.project-insanity.org/onny/nextcloud-app-podcast/-/issues/103) |
|
||||
| Add and manage subscriptions | ✅ | ❌ | ✅ | ✅ |
|
||||
| Listen synced episodes by another clients | ✅ | ✅ | ❌ | ❌ |
|
||||
| Fetch and listen new epidodes | ✅ | ❌ | ✅ | ✅ |
|
||||
| Keep track of listened episodes | ✅ | ✅ | ❌ | ✅ |
|
||||
| Fetch and listen new epidodes | ✅ | [⭕](https://github.com/pbek/nextcloud-nextpod/issues/5) | ✅ | ✅ |
|
||||
| Keep track of listened episodes | ✅ | ✅ | [⭕](https://github.com/owncloud/music/issues/1148) | ✅ |
|
||||
| Download epidodes | ✅ | ✅ | ❌ | ✅ |
|
||||
| Import and export subscriptions | ✅ | ❌ | ❌ | ❌ |
|
||||
| Sleep timer | ✅ | ❌ | [⭕](https://github.com/owncloud/music/issues/884#issuecomment-921582302) | ❌ |
|
||||
| Advanced player controls | ✅ | ❌ | ✅ | ✅ |
|
||||
| Import and export subscriptions | ✅ | ❌ | [⭕](https://github.com/owncloud/music/issues/904) | [⭕](https://git.project-insanity.org/onny/nextcloud-app-podcast/-/issues/185) |
|
||||
| Search and discover new podcasts | ✅ | ❌ | ❌ | ✅ |
|
||||
| Open episode website and RSS feed | ✅ | ✅ | ❌ | ✅ |
|
||||
| Integrate with Nextcloud search engine | ✅ | ❌ | ❌ | ✅ |
|
||||
| Integrate with [Nextcloud Notes](https://apps.nextcloud.com/apps/notes) | ❌ | ✅ | ❌ | ❌ |
|
||||
| Mobile friendly interface | ✅ | ❌ | ✅ | ✅ |
|
||||
| Support chapters | ❌ | ❌ | ❌ | ✅ |
|
||||
| Available in multiple languages | ⭕ (en/fr/de) | ❌ | ✅ | ⭕ (en/de) |
|
||||
| Support chapters | ✅ | ❌ | ❌ | ✅ |
|
||||
| Available in multiple languages | [✅](https://translate.crystalyx.net/projects/repod/gitea/) (en/fr/de) | ❌ | [✅](https://github.com/owncloud/music/issues/671#issuecomment-782746463) | [✅](https://www.transifex.com/project-insanityorg/podcast-1/dashboard/) (en/de) |
|
||||
|
||||
> Click on ⭕ to open the ticket
|
||||
|
||||
## Screenshots
|
||||
|
||||
### Homepage
|
||||
![homepage](./screens/index.png)
|
||||
|
||||
### Discover
|
||||
![homepage](./screens/discover.png)
|
||||
|
||||
### Search
|
||||
![search](./screens/search.png)
|
||||
|
||||
### Episode list
|
||||
![episodes](./screens/episodes.png)
|
||||
|
||||
### Episode description
|
||||
![modal](./screens/modal.png)
|
||||
<img src="./screens/index.png" width="230" title="Homepage" />
|
||||
<img src="./screens/discover.png" width="230" title="Discover" />
|
||||
<img src="./screens/search.png" width="230" title="Search" />
|
||||
<img src="./screens/episodes.png" width="230" title="Episode list" />
|
||||
<img src="./screens/modal.png" width="230" title="Episode description" />
|
||||
|
||||
## Clients supporting sync of GPodderSync
|
||||
|
||||
@ -68,6 +63,14 @@ Either from the official Nextcloud [app store](https://apps.nextcloud.com/apps/r
|
||||
|
||||
- Conflict with Plasma Integration Firefox addon ([#164](https://git.crystalyx.net/Xefir/repod/issues/164))
|
||||
|
||||
## Translations
|
||||
|
||||
You can contribute to translate the app in your language and you don't need to have any development background to do so !
|
||||
|
||||
Please join the effort at our **[Weblate](https://translate.crystalyx.net/projects/repod/gitea/)** project.
|
||||
|
||||
Thank you so much if you decide to participate ❤️
|
||||
|
||||
## Credits
|
||||
|
||||
- [GPodder Sync](https://github.com/thrillfall/nextcloud-gpodder) for the database API
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
## Requirements
|
||||
You need to have [GPodderSync](https://apps.nextcloud.com/apps/gpoddersync) installed to use this app!]]></description>
|
||||
<version>3.4.0</version>
|
||||
<version>3.4.1</version>
|
||||
<licence>agpl</licence>
|
||||
<author mail="xefir@crystalyx.net" homepage="https://crystalyx.net">Michel Roux</author>
|
||||
<namespace>RePod</namespace>
|
||||
|
@ -12,12 +12,18 @@
|
||||
"lint": "find . -name \\*.php -not -path './vendor/*' -not -path './vendor-bin/*' -not -path './build/*' -print0 | xargs -0 -n1 php -l",
|
||||
"cs:check": "php-cs-fixer fix --dry-run --diff",
|
||||
"cs:fix": "php-cs-fixer fix",
|
||||
"psalm": "psalm --threads=1 --no-cache --show-info=true"
|
||||
"psalm": "psalm --threads=1 --no-cache --show-info=true",
|
||||
"rector": "rector && composer cs:fix"
|
||||
},
|
||||
"require": {
|
||||
"php": "^8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"nextcloud/ocp": "^30.0.2",
|
||||
"roave/security-advisories": "dev-latest",
|
||||
"nextcloud/coding-standard": "^1.3.2",
|
||||
"nextcloud/rector": "^0.2.1",
|
||||
"rector/rector": "^1.2.10",
|
||||
"vimeo/psalm": "^5.26.1"
|
||||
},
|
||||
"config": {
|
||||
|
253
composer.lock
generated
253
composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "2bded493404c793fc0cfceedfeccc38c",
|
||||
"content-hash": "a82f9b080077d3e1ddc2ee3a0c736cf4",
|
||||
"packages": [],
|
||||
"packages-dev": [
|
||||
{
|
||||
@ -169,16 +169,16 @@
|
||||
},
|
||||
{
|
||||
"name": "composer/pcre",
|
||||
"version": "3.3.1",
|
||||
"version": "3.3.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/composer/pcre.git",
|
||||
"reference": "63aaeac21d7e775ff9bc9d45021e1745c97521c4"
|
||||
"reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/composer/pcre/zipball/63aaeac21d7e775ff9bc9d45021e1745c97521c4",
|
||||
"reference": "63aaeac21d7e775ff9bc9d45021e1745c97521c4",
|
||||
"url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e",
|
||||
"reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -188,8 +188,8 @@
|
||||
"phpstan/phpstan": "<1.11.10"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^1.11.10",
|
||||
"phpstan/phpstan-strict-rules": "^1.1",
|
||||
"phpstan/phpstan": "^1.12 || ^2",
|
||||
"phpstan/phpstan-strict-rules": "^1 || ^2",
|
||||
"phpunit/phpunit": "^8 || ^9"
|
||||
},
|
||||
"type": "library",
|
||||
@ -228,7 +228,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/composer/pcre/issues",
|
||||
"source": "https://github.com/composer/pcre/tree/3.3.1"
|
||||
"source": "https://github.com/composer/pcre/tree/3.3.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -244,7 +244,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-08-27T18:44:43+00:00"
|
||||
"time": "2024-11-12T16:29:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "composer/semver",
|
||||
@ -822,6 +822,68 @@
|
||||
},
|
||||
"time": "2024-10-19T00:42:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nextcloud/rector",
|
||||
"version": "v0.2.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nextcloud-libraries/rector.git",
|
||||
"reference": "d73ab086700564f675eda9a834b6b08410a1da7e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nextcloud-libraries/rector/zipball/d73ab086700564f675eda9a834b6b08410a1da7e",
|
||||
"reference": "d73ab086700564f675eda9a834b6b08410a1da7e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^10.5",
|
||||
"ramsey/devtools": "^2.0",
|
||||
"rector/rector": "^1.2"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"captainhook": {
|
||||
"force-install": true
|
||||
},
|
||||
"ramsey/conventional-commits": {
|
||||
"configFile": "conventional-commits.json"
|
||||
},
|
||||
"ramsey/devtools": {
|
||||
"command-prefix": "dev",
|
||||
"memory-limit": "-1"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Nextcloud\\Rector\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"AGPL-3.0-or-later"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Christoph Wurst",
|
||||
"email": "christoph@winzerhof-wurst.at",
|
||||
"homepage": "https://wuc.me"
|
||||
}
|
||||
],
|
||||
"description": "Rector upgrade rules for Nextcloud",
|
||||
"keywords": [
|
||||
"nextcloud",
|
||||
"refactoring"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/nextcloud-libraries/rector/issues",
|
||||
"source": "https://github.com/nextcloud-libraries/rector/tree/v0.2.1"
|
||||
},
|
||||
"time": "2024-10-01T12:24:08+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nikic/php-parser",
|
||||
"version": "v4.19.4",
|
||||
@ -985,16 +1047,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpdocumentor/reflection-docblock",
|
||||
"version": "5.5.1",
|
||||
"version": "5.6.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
|
||||
"reference": "0c70d2c566e899666f367ab7b80986beb3581e6f"
|
||||
"reference": "f3558a4c23426d12bffeaab463f8a8d8b681193c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/0c70d2c566e899666f367ab7b80986beb3581e6f",
|
||||
"reference": "0c70d2c566e899666f367ab7b80986beb3581e6f",
|
||||
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/f3558a4c23426d12bffeaab463f8a8d8b681193c",
|
||||
"reference": "f3558a4c23426d12bffeaab463f8a8d8b681193c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1003,7 +1065,7 @@
|
||||
"php": "^7.4 || ^8.0",
|
||||
"phpdocumentor/reflection-common": "^2.2",
|
||||
"phpdocumentor/type-resolver": "^1.7",
|
||||
"phpstan/phpdoc-parser": "^1.7",
|
||||
"phpstan/phpdoc-parser": "^1.7|^2.0",
|
||||
"webmozart/assert": "^1.9.1"
|
||||
},
|
||||
"require-dev": {
|
||||
@ -1043,29 +1105,29 @@
|
||||
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
|
||||
"support": {
|
||||
"issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues",
|
||||
"source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.5.1"
|
||||
"source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.0"
|
||||
},
|
||||
"time": "2024-11-06T11:58:54+00:00"
|
||||
"time": "2024-11-12T11:25:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpdocumentor/type-resolver",
|
||||
"version": "1.9.0",
|
||||
"version": "1.10.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpDocumentor/TypeResolver.git",
|
||||
"reference": "1fb5ba8d045f5dd984ebded5b1cc66f29459422d"
|
||||
"reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/1fb5ba8d045f5dd984ebded5b1cc66f29459422d",
|
||||
"reference": "1fb5ba8d045f5dd984ebded5b1cc66f29459422d",
|
||||
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/679e3ce485b99e84c775d28e2e96fade9a7fb50a",
|
||||
"reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"doctrine/deprecations": "^1.0",
|
||||
"php": "^7.3 || ^8.0",
|
||||
"phpdocumentor/reflection-common": "^2.0",
|
||||
"phpstan/phpdoc-parser": "^1.18"
|
||||
"phpstan/phpdoc-parser": "^1.18|^2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-tokenizer": "*",
|
||||
@ -1101,36 +1163,36 @@
|
||||
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
|
||||
"support": {
|
||||
"issues": "https://github.com/phpDocumentor/TypeResolver/issues",
|
||||
"source": "https://github.com/phpDocumentor/TypeResolver/tree/1.9.0"
|
||||
"source": "https://github.com/phpDocumentor/TypeResolver/tree/1.10.0"
|
||||
},
|
||||
"time": "2024-11-03T20:11:34+00:00"
|
||||
"time": "2024-11-09T15:12:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpdoc-parser",
|
||||
"version": "1.33.0",
|
||||
"version": "2.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpdoc-parser.git",
|
||||
"reference": "82a311fd3690fb2bf7b64d5c98f912b3dd746140"
|
||||
"reference": "c00d78fb6b29658347f9d37ebe104bffadf36299"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/82a311fd3690fb2bf7b64d5c98f912b3dd746140",
|
||||
"reference": "82a311fd3690fb2bf7b64d5c98f912b3dd746140",
|
||||
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/c00d78fb6b29658347f9d37ebe104bffadf36299",
|
||||
"reference": "c00d78fb6b29658347f9d37ebe104bffadf36299",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2 || ^8.0"
|
||||
"php": "^7.4 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/annotations": "^2.0",
|
||||
"nikic/php-parser": "^4.15",
|
||||
"nikic/php-parser": "^5.3.0",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.2",
|
||||
"phpstan/extension-installer": "^1.0",
|
||||
"phpstan/phpstan": "^1.5",
|
||||
"phpstan/phpstan-phpunit": "^1.1",
|
||||
"phpstan/phpstan-strict-rules": "^1.0",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"phpstan/phpstan": "^2.0",
|
||||
"phpstan/phpstan-phpunit": "^2.0",
|
||||
"phpstan/phpstan-strict-rules": "^2.0",
|
||||
"phpunit/phpunit": "^9.6",
|
||||
"symfony/process": "^5.2"
|
||||
},
|
||||
"type": "library",
|
||||
@ -1148,9 +1210,67 @@
|
||||
"description": "PHPDoc parser with support for nullable, intersection and generic types",
|
||||
"support": {
|
||||
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
|
||||
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.33.0"
|
||||
"source": "https://github.com/phpstan/phpdoc-parser/tree/2.0.0"
|
||||
},
|
||||
"time": "2024-10-13T11:25:22+00:00"
|
||||
"time": "2024-10-13T11:29:49+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "1.12.10",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan.git",
|
||||
"reference": "fc463b5d0fe906dcf19689be692c65c50406a071"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/fc463b5d0fe906dcf19689be692c65c50406a071",
|
||||
"reference": "fc463b5d0fe906dcf19689be692c65c50406a071",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2|^8.0"
|
||||
},
|
||||
"conflict": {
|
||||
"phpstan/phpstan-shim": "*"
|
||||
},
|
||||
"bin": [
|
||||
"phpstan",
|
||||
"phpstan.phar"
|
||||
],
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "PHPStan - PHP Static Analysis Tool",
|
||||
"keywords": [
|
||||
"dev",
|
||||
"static analysis"
|
||||
],
|
||||
"support": {
|
||||
"docs": "https://phpstan.org/user-guide/getting-started",
|
||||
"forum": "https://github.com/phpstan/phpstan/discussions",
|
||||
"issues": "https://github.com/phpstan/phpstan/issues",
|
||||
"security": "https://github.com/phpstan/phpstan/security/policy",
|
||||
"source": "https://github.com/phpstan/phpstan-src"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/ondrejmirtes",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/phpstan",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-11-11T15:37:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/clock",
|
||||
@ -1353,6 +1473,65 @@
|
||||
},
|
||||
"time": "2021-07-14T16:41:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "rector/rector",
|
||||
"version": "1.2.10",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/rectorphp/rector.git",
|
||||
"reference": "40f9cf38c05296bd32f444121336a521a293fa61"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/rectorphp/rector/zipball/40f9cf38c05296bd32f444121336a521a293fa61",
|
||||
"reference": "40f9cf38c05296bd32f444121336a521a293fa61",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2|^8.0",
|
||||
"phpstan/phpstan": "^1.12.5"
|
||||
},
|
||||
"conflict": {
|
||||
"rector/rector-doctrine": "*",
|
||||
"rector/rector-downgrade-php": "*",
|
||||
"rector/rector-phpunit": "*",
|
||||
"rector/rector-symfony": "*"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-dom": "To manipulate phpunit.xml via the custom-rule command"
|
||||
},
|
||||
"bin": [
|
||||
"bin/rector"
|
||||
],
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "Instant Upgrade and Automated Refactoring of any PHP code",
|
||||
"keywords": [
|
||||
"automation",
|
||||
"dev",
|
||||
"migration",
|
||||
"refactoring"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/rectorphp/rector/issues",
|
||||
"source": "https://github.com/rectorphp/rector/tree/1.2.10"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/tomasvotruba",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-11-08T13:59:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "roave/security-advisories",
|
||||
"version": "dev-latest",
|
||||
@ -3219,7 +3398,9 @@
|
||||
},
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {},
|
||||
"platform": {
|
||||
"php": "^8.1"
|
||||
},
|
||||
"platform-dev": {},
|
||||
"platform-overrides": {
|
||||
"php": "8.1"
|
||||
|
@ -5,8 +5,9 @@ OC.L10N.register(
|
||||
"Podcast" : "Podcast",
|
||||
"RePod" : "RePod",
|
||||
"🔊 Browse, manage and listen to podcasts" : "🔊 Suchen, Verwalten und Anhören von Podcasts",
|
||||
"## Features\n- 🔍 Browse and subscribe huge collection of podcasts\n- 🔊 Listen to episodes directly in Nextcloud\n- 🌐 Sync your activity with [AntennaPod](https://antennapod.org/) and [other apps](https://git.crystalyx.net/Xefir/repod#clients-supporting-sync-of-gpoddersync)\n- 📱 Mobile friendly interface\n- 📡 Import and export your subscriptions\n- ➡️ Full features comparison [here](https://git.crystalyx.net/Xefir/repod#comparaison-with-similar-apps-for-nextcloud)\n\n## Requirements\nYou need to have [GPodderSync](https://apps.nextcloud.com/apps/gpoddersync) installed to use this app!" : "## Funktionen\n- 🔍 Durchsuchen und abonnieren einer großen Sammlung von Podcasts\n- 🔊 Episoden direkt in Nextcloud anhören\n- 🌐 Synchronisiere deine Aktivität mit [AntennaPod](https://antennapod.org/)\n- 📱 Mobile-freundliche Schnittstelle\n- 📡 Importieren und Exportieren Ihrer Abonnements\n\n## Voraussetzungen\nDu musst [GPodderSync](https://apps.nextcloud.com/apps/gpoddersync) installiert haben, um diese App zu benutzen!",
|
||||
"## Features\n- 🔍 Browse and subscribe huge collection of podcasts\n- 🔊 Listen to episodes directly in Nextcloud\n- 🌐 Sync your activity with [AntennaPod](https://antennapod.org/) and [other apps](https://git.crystalyx.net/Xefir/repod#clients-supporting-sync-of-gpoddersync)\n- 📱 Mobile friendly interface\n- 📡 Import and export your subscriptions\n- ➡️ Full features comparison [here](https://git.crystalyx.net/Xefir/repod#comparaison-with-similar-apps-for-nextcloud)\n\n## Requirements\nYou need to have [GPodderSync](https://apps.nextcloud.com/apps/gpoddersync) installed to use this app!" : "## Funktionen\n- 🔍 Durchsuchen und abonnieren einer großen Sammlung von Podcasts\n- 🔊 Episoden direkt in Nextcloud anhören\n- 🌐 Synchronisiere deine Aktivität mit [AntennaPod](https://antennapod.org/)\n- 📱 Mobile-freundliche Schnittstelle\n- 📡 Importieren und Exportieren Ihrer Abonnements\n- ➡️ Vollständiger Funktionsvergleich [hier](https://git.crystalyx.net/Xefir/repod#comparaison-with-similar-apps-for-nextcloud)\n\n## Voraussetzungen\nDu musst [GPodderSync](https://apps.nextcloud.com/apps/gpoddersync) installiert haben, um diese App zu benutzen!",
|
||||
"Download" : "Herunterladen",
|
||||
"Skip to {match}" : "Springen zu {match}",
|
||||
"Add a RSS link" : "Einen RSS-Link hinzufügen",
|
||||
"Subscribe" : "Abonnieren",
|
||||
"Error while adding the feed" : "Fehler beim Hinzufügen des Feeds",
|
||||
@ -55,4 +56,4 @@ OC.L10N.register(
|
||||
"No favorites" : "Keine Favoriten",
|
||||
"A browser extension conflict with RePod" : "Ein Browser-Erweiterungskonflikt mit RePod"
|
||||
},
|
||||
"");
|
||||
"nplurals=2; plural=n != 1;");
|
||||
|
@ -3,8 +3,9 @@
|
||||
"Podcast" : "Podcast",
|
||||
"RePod" : "RePod",
|
||||
"🔊 Browse, manage and listen to podcasts" : "🔊 Suchen, Verwalten und Anhören von Podcasts",
|
||||
"## Features\n- 🔍 Browse and subscribe huge collection of podcasts\n- 🔊 Listen to episodes directly in Nextcloud\n- 🌐 Sync your activity with [AntennaPod](https://antennapod.org/) and [other apps](https://git.crystalyx.net/Xefir/repod#clients-supporting-sync-of-gpoddersync)\n- 📱 Mobile friendly interface\n- 📡 Import and export your subscriptions\n- ➡️ Full features comparison [here](https://git.crystalyx.net/Xefir/repod#comparaison-with-similar-apps-for-nextcloud)\n\n## Requirements\nYou need to have [GPodderSync](https://apps.nextcloud.com/apps/gpoddersync) installed to use this app!" : "## Funktionen\n- 🔍 Durchsuchen und abonnieren einer großen Sammlung von Podcasts\n- 🔊 Episoden direkt in Nextcloud anhören\n- 🌐 Synchronisiere deine Aktivität mit [AntennaPod](https://antennapod.org/)\n- 📱 Mobile-freundliche Schnittstelle\n- 📡 Importieren und Exportieren Ihrer Abonnements\n\n## Voraussetzungen\nDu musst [GPodderSync](https://apps.nextcloud.com/apps/gpoddersync) installiert haben, um diese App zu benutzen!",
|
||||
"## Features\n- 🔍 Browse and subscribe huge collection of podcasts\n- 🔊 Listen to episodes directly in Nextcloud\n- 🌐 Sync your activity with [AntennaPod](https://antennapod.org/) and [other apps](https://git.crystalyx.net/Xefir/repod#clients-supporting-sync-of-gpoddersync)\n- 📱 Mobile friendly interface\n- 📡 Import and export your subscriptions\n- ➡️ Full features comparison [here](https://git.crystalyx.net/Xefir/repod#comparaison-with-similar-apps-for-nextcloud)\n\n## Requirements\nYou need to have [GPodderSync](https://apps.nextcloud.com/apps/gpoddersync) installed to use this app!" : "## Funktionen\n- 🔍 Durchsuchen und abonnieren einer großen Sammlung von Podcasts\n- 🔊 Episoden direkt in Nextcloud anhören\n- 🌐 Synchronisiere deine Aktivität mit [AntennaPod](https://antennapod.org/)\n- 📱 Mobile-freundliche Schnittstelle\n- 📡 Importieren und Exportieren Ihrer Abonnements\n- ➡️ Vollständiger Funktionsvergleich [hier](https://git.crystalyx.net/Xefir/repod#comparaison-with-similar-apps-for-nextcloud)\n\n## Voraussetzungen\nDu musst [GPodderSync](https://apps.nextcloud.com/apps/gpoddersync) installiert haben, um diese App zu benutzen!",
|
||||
"Download" : "Herunterladen",
|
||||
"Skip to {match}" : "Springen zu {match}",
|
||||
"Add a RSS link" : "Einen RSS-Link hinzufügen",
|
||||
"Subscribe" : "Abonnieren",
|
||||
"Error while adding the feed" : "Fehler beim Hinzufügen des Feeds",
|
||||
@ -52,5 +53,5 @@
|
||||
"Pin some subscriptions to see their latest updates" : "Pinne einige Abonnements, um ihre neuesten Updates zu sehen",
|
||||
"No favorites" : "Keine Favoriten",
|
||||
"A browser extension conflict with RePod" : "Ein Browser-Erweiterungskonflikt mit RePod"
|
||||
},"pluralForm" :""
|
||||
},"pluralForm" :"nplurals=2; plural=n != 1;"
|
||||
}
|
@ -7,6 +7,7 @@ OC.L10N.register(
|
||||
"🔊 Browse, manage and listen to podcasts" : "🔊 Parcourir, gérer et écouter vos podcasts",
|
||||
"## Features\n- 🔍 Browse and subscribe huge collection of podcasts\n- 🔊 Listen to episodes directly in Nextcloud\n- 🌐 Sync your activity with [AntennaPod](https://antennapod.org/) and [other apps](https://git.crystalyx.net/Xefir/repod#clients-supporting-sync-of-gpoddersync)\n- 📱 Mobile friendly interface\n- 📡 Import and export your subscriptions\n- ➡️ Full features comparison [here](https://git.crystalyx.net/Xefir/repod#comparaison-with-similar-apps-for-nextcloud)\n\n## Requirements\nYou need to have [GPodderSync](https://apps.nextcloud.com/apps/gpoddersync) installed to use this app!" : "## Fonctionnalités\n- 🔍 Parcourir et s'abonner à une grande collections de podcasts\n- 🔊 Écouter vos épisodes directement sur Nextcloud\n- 🌐 Synchroniser son activité avec [AntennaPod](https://antennapod.org/) et d'autres [applications](https://git.crystalyx.net/Xefir/repod#clients-supporting-sync-of-gpoddersync)\n- 📱 Interface optimisée pour mobiles et ordinateurs\n- 📡 Import/export de ses abonnements\n- ➡️ Tableau récapitulatif complet des fonctionnalitées [ici](https://git.crystalyx.net/Xefir/repod#comparaison-with-similar-apps-for-nextcloud)\n\n## Pré-requis\nVous devez avoir [GPodderSync](https://apps.nextcloud.com/apps/gpoddersync) installé pour utiliser cette application !",
|
||||
"Download" : "Télécharger",
|
||||
"Skip to {match}" : "Sauter à {match}",
|
||||
"Add a RSS link" : "Ajouter un lien RSS",
|
||||
"Subscribe" : "S'abonner",
|
||||
"Error while adding the feed" : "Erreur lors de l'ajout du flux",
|
||||
|
@ -5,6 +5,7 @@
|
||||
"🔊 Browse, manage and listen to podcasts" : "🔊 Parcourir, gérer et écouter vos podcasts",
|
||||
"## Features\n- 🔍 Browse and subscribe huge collection of podcasts\n- 🔊 Listen to episodes directly in Nextcloud\n- 🌐 Sync your activity with [AntennaPod](https://antennapod.org/) and [other apps](https://git.crystalyx.net/Xefir/repod#clients-supporting-sync-of-gpoddersync)\n- 📱 Mobile friendly interface\n- 📡 Import and export your subscriptions\n- ➡️ Full features comparison [here](https://git.crystalyx.net/Xefir/repod#comparaison-with-similar-apps-for-nextcloud)\n\n## Requirements\nYou need to have [GPodderSync](https://apps.nextcloud.com/apps/gpoddersync) installed to use this app!" : "## Fonctionnalités\n- 🔍 Parcourir et s'abonner à une grande collections de podcasts\n- 🔊 Écouter vos épisodes directement sur Nextcloud\n- 🌐 Synchroniser son activité avec [AntennaPod](https://antennapod.org/) et d'autres [applications](https://git.crystalyx.net/Xefir/repod#clients-supporting-sync-of-gpoddersync)\n- 📱 Interface optimisée pour mobiles et ordinateurs\n- 📡 Import/export de ses abonnements\n- ➡️ Tableau récapitulatif complet des fonctionnalitées [ici](https://git.crystalyx.net/Xefir/repod#comparaison-with-similar-apps-for-nextcloud)\n\n## Pré-requis\nVous devez avoir [GPodderSync](https://apps.nextcloud.com/apps/gpoddersync) installé pour utiliser cette application !",
|
||||
"Download" : "Télécharger",
|
||||
"Skip to {match}" : "Sauter à {match}",
|
||||
"Add a RSS link" : "Ajouter un lien RSS",
|
||||
"Subscribe" : "S'abonner",
|
||||
"Error while adding the feed" : "Erreur lors de l'ajout du flux",
|
||||
|
@ -16,6 +16,7 @@ use OCP\AppFramework\Services\IInitialState;
|
||||
class Application extends App implements IBootstrap
|
||||
{
|
||||
public const APP_ID = 'repod';
|
||||
|
||||
private const GPODDERSYNC_ID = 'gpoddersync';
|
||||
|
||||
public function __construct() {
|
||||
@ -40,7 +41,7 @@ class Application extends App implements IBootstrap
|
||||
if (!$gpoddersync) {
|
||||
try {
|
||||
$appManager->enableApp(self::GPODDERSYNC_ID);
|
||||
} catch (AppPathNotFoundException $e) {
|
||||
} catch (AppPathNotFoundException) {
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,10 +22,10 @@ class EpisodesController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
IRequest $request,
|
||||
private EpisodeActionReader $episodeActionReader,
|
||||
private EpisodeActionRepository $episodeActionRepository,
|
||||
private IClientService $clientService,
|
||||
private UserService $userService
|
||||
private readonly EpisodeActionReader $episodeActionReader,
|
||||
private readonly EpisodeActionRepository $episodeActionRepository,
|
||||
private readonly IClientService $clientService,
|
||||
private readonly UserService $userService
|
||||
) {
|
||||
parent::__construct(Application::APP_ID, $request);
|
||||
}
|
||||
@ -37,8 +37,8 @@ class EpisodesController extends Controller
|
||||
$client = $this->clientService->newClient();
|
||||
$feed = $client->get($url);
|
||||
$episodes = $this->episodeActionReader->parseRssXml((string) $feed->getBody());
|
||||
usort($episodes, fn (EpisodeActionExtraData $a, EpisodeActionExtraData $b) => $b->getPubDate() <=> $a->getPubDate());
|
||||
$episodes = array_values(array_intersect_key($episodes, array_unique(array_map(fn (EpisodeActionExtraData $episode) => $episode->getGuid(), $episodes))));
|
||||
usort($episodes, fn (EpisodeActionExtraData $a, EpisodeActionExtraData $b): int => $b->getPubDate() <=> $a->getPubDate());
|
||||
$episodes = array_values(array_intersect_key($episodes, array_unique(array_map(fn (EpisodeActionExtraData $episode): string => $episode->getGuid(), $episodes))));
|
||||
|
||||
return new JSONResponse($episodes, $feed->getStatusCode());
|
||||
}
|
||||
|
@ -22,11 +22,11 @@ class OpmlController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
IRequest $request,
|
||||
private IL10N $l10n,
|
||||
private PodcastDataReader $podcastDataReader,
|
||||
private PodcastMetricsReader $podcastMetricsReader,
|
||||
private SubscriptionChangeSaver $subscriptionChangeSaver,
|
||||
private UserService $userService
|
||||
private readonly IL10N $l10n,
|
||||
private readonly PodcastDataReader $podcastDataReader,
|
||||
private readonly PodcastMetricsReader $podcastMetricsReader,
|
||||
private readonly SubscriptionChangeSaver $subscriptionChangeSaver,
|
||||
private readonly UserService $userService
|
||||
) {
|
||||
parent::__construct(Application::APP_ID, $request);
|
||||
}
|
||||
@ -55,7 +55,7 @@ class OpmlController extends Controller
|
||||
foreach ($subscriptions as $subscription) {
|
||||
try {
|
||||
$podcast = $this->podcastDataReader->getCachedOrFetchPodcastData($subscription->getUrl(), $this->userService->getUserUID());
|
||||
} catch (\Exception $e) {
|
||||
} catch (\Exception) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -11,15 +11,13 @@ use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
|
||||
use OCP\AppFramework\Http\ContentSecurityPolicy;
|
||||
use OCP\AppFramework\Http\TemplateResponse;
|
||||
use OCP\IConfig;
|
||||
use OCP\IRequest;
|
||||
use OCP\Util;
|
||||
|
||||
class PageController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
IRequest $request,
|
||||
private IConfig $config
|
||||
IRequest $request
|
||||
) {
|
||||
parent::__construct(Application::APP_ID, $request);
|
||||
}
|
||||
|
@ -20,9 +20,9 @@ class PodcastController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
IRequest $request,
|
||||
private ICacheFactory $cacheFactory,
|
||||
private IClientService $clientService,
|
||||
private PodcastDataReader $podcastDataReader
|
||||
private readonly ICacheFactory $cacheFactory,
|
||||
private readonly IClientService $clientService,
|
||||
private readonly PodcastDataReader $podcastDataReader
|
||||
) {
|
||||
parent::__construct(Application::APP_ID, $request);
|
||||
}
|
||||
@ -36,7 +36,7 @@ class PodcastController extends Controller
|
||||
if ($this->cacheFactory->isLocalCacheAvailable()) {
|
||||
try {
|
||||
$podcast = $this->podcastDataReader->tryGetCachedPodcastData($url);
|
||||
} catch (\Exception $e) {
|
||||
} catch (\Exception) {
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ class PodcastController extends Controller
|
||||
if ($this->cacheFactory->isLocalCacheAvailable()) {
|
||||
try {
|
||||
$this->podcastDataReader->trySetCachedPodcastData($url, $podcast);
|
||||
} catch (\Exception $e) {
|
||||
} catch (\Exception) {
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ class SearchController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
IRequest $request,
|
||||
private MultiPodService $multiPodService
|
||||
private readonly MultiPodService $multiPodService
|
||||
) {
|
||||
parent::__construct(Application::APP_ID, $request);
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ class ToplistController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
IRequest $request,
|
||||
private FyydService $fyydService
|
||||
private readonly FyydService $fyydService
|
||||
) {
|
||||
parent::__construct(Application::APP_ID, $request);
|
||||
}
|
||||
|
@ -28,22 +28,22 @@ use OCA\GPodderSync\Core\EpisodeAction\EpisodeAction;
|
||||
* action: ?EpisodeActionType
|
||||
* }
|
||||
*/
|
||||
class EpisodeActionExtraData implements \JsonSerializable
|
||||
class EpisodeActionExtraData implements \JsonSerializable, \Stringable
|
||||
{
|
||||
public function __construct(
|
||||
private string $title,
|
||||
private ?string $url,
|
||||
private string $name,
|
||||
private ?string $link,
|
||||
private ?string $image,
|
||||
private ?string $description,
|
||||
private int $fetchedAtUnix,
|
||||
private string $guid,
|
||||
private ?string $type,
|
||||
private ?int $size,
|
||||
private ?\DateTime $pubDate,
|
||||
private ?string $duration,
|
||||
private ?EpisodeAction $action
|
||||
private readonly string $title,
|
||||
private readonly ?string $url,
|
||||
private readonly string $name,
|
||||
private readonly ?string $link,
|
||||
private readonly ?string $image,
|
||||
private readonly ?string $description,
|
||||
private readonly int $fetchedAtUnix,
|
||||
private readonly string $guid,
|
||||
private readonly ?string $type,
|
||||
private readonly ?int $size,
|
||||
private readonly ?\DateTime $pubDate,
|
||||
private readonly ?string $duration,
|
||||
private readonly ?EpisodeAction $action
|
||||
) {}
|
||||
|
||||
public function __toString(): string {
|
||||
@ -120,7 +120,7 @@ class EpisodeActionExtraData implements \JsonSerializable
|
||||
'size' => $this->size,
|
||||
'pubDate' => $this->pubDate,
|
||||
'duration' => $this->duration,
|
||||
'action' => $this->action ? $this->action->toArray() : null,
|
||||
'action' => $this->action instanceof EpisodeAction ? $this->action->toArray() : null,
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -11,8 +11,8 @@ use OCA\RePod\Service\UserService;
|
||||
class EpisodeActionReader extends CoreEpisodeActionReader
|
||||
{
|
||||
public function __construct(
|
||||
private EpisodeActionRepository $episodeActionRepository,
|
||||
private UserService $userService
|
||||
private readonly EpisodeActionRepository $episodeActionRepository,
|
||||
private readonly UserService $userService
|
||||
) {}
|
||||
|
||||
/**
|
||||
@ -20,7 +20,8 @@ class EpisodeActionReader extends CoreEpisodeActionReader
|
||||
* Specs : https://github.com/Podcast-Standards-Project/PSP-1-Podcast-RSS-Specification/blob/main/README.md.
|
||||
*
|
||||
* @return EpisodeActionExtraData[]
|
||||
* @throws \Exception if the XML data could not be parsed
|
||||
*
|
||||
* @throws \Exception if the XML data could not be parsed
|
||||
*/
|
||||
public function parseRssXml(string $xmlString, ?int $fetchedAtUnix = null): array {
|
||||
$episodes = [];
|
||||
@ -92,9 +93,6 @@ class EpisodeActionReader extends CoreEpisodeActionReader
|
||||
$description = $this->stringOrNull($iTunesItemChildren->summary);
|
||||
}
|
||||
|
||||
// Remove tags
|
||||
$description = strip_tags(str_replace(['<br>', '<br/>', '<br />'], "\n", $description ?? ''));
|
||||
|
||||
// Get episode duration
|
||||
if (isset($iTunesItemChildren)) {
|
||||
$duration = $this->stringOrNull($iTunesItemChildren->duration);
|
||||
@ -107,7 +105,7 @@ class EpisodeActionReader extends CoreEpisodeActionReader
|
||||
if (isset($pubDate)) {
|
||||
try {
|
||||
$pubDate = new \DateTime($pubDate);
|
||||
} catch (\Exception $e) {
|
||||
} catch (\Exception) {
|
||||
$pubDate = null;
|
||||
}
|
||||
}
|
||||
|
@ -13,9 +13,9 @@ class FyydService implements IPodProvider
|
||||
private const BASE_URL = 'https://api.fyyd.de/0.2/';
|
||||
|
||||
public function __construct(
|
||||
private IClientService $clientService,
|
||||
private LoggerInterface $logger,
|
||||
private UserService $userService
|
||||
private readonly IClientService $clientService,
|
||||
private readonly LoggerInterface $logger,
|
||||
private readonly UserService $userService
|
||||
) {}
|
||||
|
||||
public function search(string $value): array {
|
||||
@ -94,8 +94,8 @@ class FyydService implements IPodProvider
|
||||
if (array_key_exists('data', $langJson) && is_array($langJson['data'])) {
|
||||
$language = in_array($userLang, $langJson['data']) ? $userLang : 'en';
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$this->logger->error($e->getMessage(), $e->getTrace());
|
||||
} catch (\Exception $exception) {
|
||||
$this->logger->error($exception->getMessage(), $exception->getTrace());
|
||||
}
|
||||
|
||||
$podcastClient = $this->clientService->newClient();
|
||||
|
@ -12,8 +12,8 @@ class ItunesService implements IPodProvider
|
||||
private const BASE_URL = 'https://itunes.apple.com/';
|
||||
|
||||
public function __construct(
|
||||
private IClientService $clientService,
|
||||
private UserService $userService
|
||||
private readonly IClientService $clientService,
|
||||
private readonly UserService $userService
|
||||
) {}
|
||||
|
||||
public function search(string $value): array {
|
||||
|
@ -17,7 +17,7 @@ class MultiPodService implements IPodProvider
|
||||
public function __construct(
|
||||
FyydService $fyydService,
|
||||
ItunesService $itunesService,
|
||||
private LoggerInterface $logger
|
||||
private readonly LoggerInterface $logger
|
||||
) {
|
||||
$this->providers = [$fyydService, $itunesService];
|
||||
}
|
||||
@ -36,7 +36,7 @@ class MultiPodService implements IPodProvider
|
||||
}
|
||||
}
|
||||
|
||||
usort($podcasts, fn (PodcastData $a, PodcastData $b) => $b->getFetchedAtUnix() <=> $a->getFetchedAtUnix());
|
||||
usort($podcasts, fn (PodcastData $a, PodcastData $b): int => $b->getFetchedAtUnix() <=> $a->getFetchedAtUnix());
|
||||
|
||||
return array_values(
|
||||
array_intersect_key(
|
||||
|
@ -16,9 +16,9 @@ use OCP\Search\SearchResultEntry;
|
||||
class SearchProvider implements IProvider
|
||||
{
|
||||
public function __construct(
|
||||
private IL10N $l10n,
|
||||
private IURLGenerator $urlGenerator,
|
||||
private MultiPodService $multiPodService
|
||||
private readonly IL10N $l10n,
|
||||
private readonly IURLGenerator $urlGenerator,
|
||||
private readonly MultiPodService $multiPodService
|
||||
) {}
|
||||
|
||||
public function getId(): string {
|
||||
@ -30,7 +30,7 @@ class SearchProvider implements IProvider
|
||||
}
|
||||
|
||||
public function getOrder(string $route, array $routeParameters): int {
|
||||
if (0 === strpos($route, Application::APP_ID.'.')) {
|
||||
if (str_starts_with($route, Application::APP_ID.'.')) {
|
||||
// Active app, prefer my results
|
||||
return -1;
|
||||
}
|
||||
|
@ -10,8 +10,8 @@ use OCP\L10N\IFactory;
|
||||
class UserService
|
||||
{
|
||||
public function __construct(
|
||||
private IFactory $l10n,
|
||||
private IUserSession $userSession
|
||||
private readonly IFactory $l10n,
|
||||
private readonly IUserSession $userSession
|
||||
) {}
|
||||
|
||||
public function getUserUID(): string {
|
||||
@ -27,7 +27,7 @@ class UserService
|
||||
public function getCountryCode(): string {
|
||||
$isoCodes = explode('_', $this->getIsoCode());
|
||||
|
||||
return isset($isoCodes[1]) ? $isoCodes[1] : 'us';
|
||||
return $isoCodes[1] ?? 'us';
|
||||
}
|
||||
|
||||
public function getLangCode(): string {
|
||||
|
710
package-lock.json
generated
710
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
22
package.json
22
package.json
@ -1,19 +1,20 @@
|
||||
{
|
||||
"name": "repod",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "vue-tsc && vite build",
|
||||
"build": "vite build",
|
||||
"dev": "vite --mode development build",
|
||||
"watch": "vite --mode development build --watch",
|
||||
"lint": "vue-tsc && eslint src",
|
||||
"lint:fix": "vue-tsc && eslint src --fix",
|
||||
"stylelint": "stylelint src/**/*.vue src/**/*.scss src/**/*.css",
|
||||
"stylelint:fix": "stylelint src/**/*.vue src/**/*.scss src/**/*.css --fix"
|
||||
"stylelint:fix": "stylelint src/**/*.vue src/**/*.scss src/**/*.css --fix",
|
||||
"watch": "vite --mode development build --watch"
|
||||
},
|
||||
"type": "module",
|
||||
"browserslist": [
|
||||
"extends @nextcloud/browserslist-config"
|
||||
],
|
||||
"prettier": "@nextcloud/prettier-config",
|
||||
"dependencies": {
|
||||
"@formatjs/intl-segmenter": "^11.7.3",
|
||||
"@nextcloud/axios": "^2.5.1",
|
||||
@ -22,12 +23,12 @@
|
||||
"@nextcloud/router": "^3.0.1",
|
||||
"@nextcloud/vite-config": "^2.2.2",
|
||||
"@nextcloud/vue": "9.0.0-alpha.5",
|
||||
"dompurify": "^3.1.7",
|
||||
"dompurify": "^3.2.0",
|
||||
"linkify-html": "^4.1.3",
|
||||
"pinia": "^2.2.6",
|
||||
"toastify-js": "^1.12.0",
|
||||
"vite": "^5.4.10",
|
||||
"vue": "^3.5.12",
|
||||
"vite": "^5.4.11",
|
||||
"vue": "^3.5.13",
|
||||
"vue-material-design-icons": "^5.3.1",
|
||||
"vue-router": "^4.4.5"
|
||||
},
|
||||
@ -38,14 +39,11 @@
|
||||
"@nextcloud/stylelint-config": "^3.0.1",
|
||||
"@types/toastify-js": "^1.12.3",
|
||||
"@vue/eslint-config-typescript": "^13",
|
||||
"@vue/tsconfig": "^0.5.1",
|
||||
"@vue/tsconfig": "^0.6.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-pinia": "^0.4.1",
|
||||
"eslint-plugin-prettier": "^5.2.1",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "5.5",
|
||||
"vue-eslint-parser": "^9.4.3",
|
||||
"vue-tsc": "^2.1.10"
|
||||
},
|
||||
"prettier": "@nextcloud/prettier-config"
|
||||
}
|
||||
}
|
||||
|
34
rector.php
Normal file
34
rector.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Nextcloud\Rector\Set\NextcloudSets;
|
||||
use Rector\Config\RectorConfig;
|
||||
|
||||
return RectorConfig::configure()
|
||||
->withPaths([
|
||||
__DIR__.'/appinfo',
|
||||
__DIR__.'/lib',
|
||||
])
|
||||
->withPhpSets(php81: true)
|
||||
->withSets([
|
||||
NextcloudSets::NEXTCLOUD_27,
|
||||
])
|
||||
->withPreparedSets(
|
||||
deadCode: true,
|
||||
codeQuality: true,
|
||||
codingStyle: true,
|
||||
typeDeclarations: true,
|
||||
privatization: true,
|
||||
instanceOf: true,
|
||||
earlyReturn: true,
|
||||
strictBooleans: true,
|
||||
rectorPreset: true,
|
||||
phpunitCodeQuality: true,
|
||||
doctrineCodeQuality: true,
|
||||
symfonyCodeQuality: true,
|
||||
symfonyConfigs: true,
|
||||
twig: true,
|
||||
phpunit: true,
|
||||
)
|
||||
;
|
@ -1,3 +1,4 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json"
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"rangeStrategy": "bump"
|
||||
}
|
||||
|
@ -1,22 +1,44 @@
|
||||
<template>
|
||||
<div v-sanitize="source" class="html" />
|
||||
<div ref="html" v-sanitize="source" class="html" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import dompurify from 'dompurify'
|
||||
import linkifyHtml from 'linkify-html'
|
||||
import { mapActions } from 'pinia'
|
||||
import { t } from '@nextcloud/l10n'
|
||||
import { timeToSeconds } from '../../utils/time.ts'
|
||||
import { usePlayer } from '../../store/player.ts'
|
||||
|
||||
export default {
|
||||
name: 'SafeHtml',
|
||||
directives: {
|
||||
sanitize: {
|
||||
mounted(el, binding) {
|
||||
el.innerHTML = dompurify.sanitize(
|
||||
linkifyHtml(binding.value, {
|
||||
nl2br: true,
|
||||
target: '_blank',
|
||||
}),
|
||||
)
|
||||
el.innerHTML = dompurify
|
||||
.sanitize(
|
||||
linkifyHtml(binding.value, {
|
||||
nl2br: true,
|
||||
target: '_blank',
|
||||
}),
|
||||
)
|
||||
.replace(
|
||||
/(([0-9]?[0-9]):)?([0-5]?[0-9]):([0-5][0-9])/g,
|
||||
(
|
||||
match,
|
||||
noop: string,
|
||||
hours: string,
|
||||
minutes: string,
|
||||
seconds: string,
|
||||
) =>
|
||||
`<seekable time="${timeToSeconds(
|
||||
parseInt(hours),
|
||||
parseInt(minutes),
|
||||
parseInt(seconds),
|
||||
)}" title="${t('repod', 'Skip to {match}', { match })}">${
|
||||
match
|
||||
}</seekable>`,
|
||||
)
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -26,11 +48,31 @@ export default {
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
const seekables = (this.$refs.html as HTMLElement).querySelectorAll(
|
||||
'seekable',
|
||||
)
|
||||
for (const seekable of seekables) {
|
||||
seekable.addEventListener('click', (event) => {
|
||||
this.seek(
|
||||
parseInt(
|
||||
(event.target as HTMLElement).getAttribute('time') || '',
|
||||
),
|
||||
)
|
||||
this.play()
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions(usePlayer, ['play', 'seek']),
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.html a {
|
||||
.html a,
|
||||
seekable {
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
|
@ -11,7 +11,6 @@
|
||||
:name="episode.name"
|
||||
:one-line="oneLine"
|
||||
:style="{ opacity: hasEnded(episode) ? 0.4 : 1 }"
|
||||
:title="episode.description"
|
||||
@click="modalEpisode = episode">
|
||||
<template #actions>
|
||||
<NcActionButton
|
||||
|
@ -55,6 +55,7 @@ export default {
|
||||
<style scoped>
|
||||
.controls {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.pointer {
|
||||
|
@ -51,3 +51,16 @@ export const durationToSeconds = (duration: string): number => {
|
||||
seconds += splitDuration.length > 2 ? parseInt(splitDuration[2]) * 60 * 60 : 0
|
||||
return seconds
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert splitted time to seconds
|
||||
* @param {number} hours The number of seconds
|
||||
* @param {number} minutes The number of seconds
|
||||
* @param {number} seconds The number of seconds
|
||||
* @return {number}
|
||||
*/
|
||||
export const timeToSeconds = (
|
||||
hours: number,
|
||||
minutes: number,
|
||||
seconds: number,
|
||||
): number => hours * 3600 + minutes * 60 + seconds
|
||||
|
@ -7,8 +7,10 @@ namespace OCA\GPodderSync\Core\EpisodeAction;
|
||||
class EpisodeActionReader
|
||||
{
|
||||
/**
|
||||
* @param array $episodeActionsArray []
|
||||
* @param array $episodeActionsArray []
|
||||
*
|
||||
* @return EpisodeAction[]
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function fromArray(array $episodeActionsArray) {}
|
||||
|
@ -29,7 +29,8 @@ class PodcastData implements \JsonSerializable
|
||||
|
||||
/**
|
||||
* @return PodcastData
|
||||
* @throws \Exception if the XML data could not be parsed
|
||||
*
|
||||
* @throws \Exception if the XML data could not be parsed
|
||||
*/
|
||||
public static function parseRssXml(string $xmlString, ?int $fetchedAtUnix = null) {}
|
||||
|
||||
@ -81,7 +82,8 @@ class PodcastData implements \JsonSerializable
|
||||
public function jsonSerialize(): mixed {}
|
||||
|
||||
/**
|
||||
* @param PodcastDataType $data
|
||||
* @param PodcastDataType $data
|
||||
*
|
||||
* @return PodcastData
|
||||
*/
|
||||
public static function fromArray(array $data) {}
|
||||
|
@ -21,6 +21,7 @@ class EpisodeActionMapper extends QBMapper
|
||||
|
||||
/**
|
||||
* @return EpisodeActionEntity[]
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function findAll(int $sinceTimestamp, string $userId) {}
|
||||
|
@ -14,12 +14,14 @@ class EpisodeActionWriter
|
||||
|
||||
/**
|
||||
* @return EpisodeActionEntity
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function save(EpisodeActionEntity $episodeActionEntity) {}
|
||||
|
||||
/**
|
||||
* @return EpisodeActionEntity
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function update(EpisodeActionEntity $episodeActionEntity) {}
|
||||
|
@ -1,20 +1,22 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the Nextcloud package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
# OiledAmoeba <florian+crystalyx@ruhnke.cloud>, 2024.
|
||||
# Michel Roux <xefir@crystalyx.net>, 2024.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Nextcloud 3.14159\n"
|
||||
"Report-Msgid-Bugs-To: translations\\@example.com\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: OiledAmoeba <florian+crystalyx@ruhnke.cloud>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"PO-Revision-Date: 2024-11-15 21:02+0000\n"
|
||||
"Last-Translator: Michel Roux <xefir@crystalyx.net>\n"
|
||||
"Language-Team: German <https://translate.crystalyx.net/projects/repod/gitea/"
|
||||
"de/>\n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.8.3\n"
|
||||
|
||||
msgid "RePod Subscriptions"
|
||||
msgstr "RePod Abonnements"
|
||||
@ -28,6 +30,7 @@ msgstr "RePod"
|
||||
msgid "🔊 Browse, manage and listen to podcasts"
|
||||
msgstr "🔊 Suchen, Verwalten und Anhören von Podcasts"
|
||||
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"## Features\n"
|
||||
"- 🔍 Browse and subscribe huge collection of podcasts\n"
|
||||
@ -47,9 +50,12 @@ msgstr ""
|
||||
"## Funktionen\n"
|
||||
"- 🔍 Durchsuchen und abonnieren einer großen Sammlung von Podcasts\n"
|
||||
"- 🔊 Episoden direkt in Nextcloud anhören\n"
|
||||
"- 🌐 Synchronisiere deine Aktivität mit [AntennaPod](https://antennapod.org/)\n"
|
||||
"- 🌐 Synchronisiere deine Aktivität mit [AntennaPod](https://antennapod.org/)"
|
||||
"\n"
|
||||
"- 📱 Mobile-freundliche Schnittstelle\n"
|
||||
"- 📡 Importieren und Exportieren Ihrer Abonnements\n"
|
||||
"- ➡️ Vollständiger Funktionsvergleich [hier](https://git.crystalyx.net/Xefir/"
|
||||
"repod#comparaison-with-similar-apps-for-nextcloud)\n"
|
||||
"\n"
|
||||
"## Voraussetzungen\n"
|
||||
"Du musst [GPodderSync](https://apps.nextcloud.com/apps/gpoddersync) "
|
||||
@ -58,6 +64,10 @@ msgstr ""
|
||||
msgid "Download"
|
||||
msgstr "Herunterladen"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Skip to {match}"
|
||||
msgstr "Springen zu {match}"
|
||||
|
||||
msgid "Add a RSS link"
|
||||
msgstr "Einen RSS-Link hinzufügen"
|
||||
|
||||
@ -82,6 +92,7 @@ msgstr "Titel können nicht abgerufen werden"
|
||||
msgid "Copy feed"
|
||||
msgstr "Feed kopieren"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Link copied to the clipboard"
|
||||
msgstr "Der Link des Feeds wurde in die Zwischenablage kopiert"
|
||||
|
||||
@ -91,6 +102,7 @@ msgstr "Abspielen"
|
||||
msgid "Stop"
|
||||
msgstr "Stopp"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Read"
|
||||
msgstr "Gelesen"
|
||||
|
||||
@ -103,18 +115,22 @@ msgstr "Kann den Status der Folge nicht ändern"
|
||||
msgid "Could not fetch episodes"
|
||||
msgstr "Folgen können nicht abgerufen werden"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Rewind 10 seconds"
|
||||
msgstr "10 Sekunden zurückspulen"
|
||||
|
||||
msgid "Pause"
|
||||
msgstr "Pause"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Fast forward 30 seconds"
|
||||
msgstr "30 Sekunden vorspulen"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Mute"
|
||||
msgstr "Stumm"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Unmute"
|
||||
msgstr "Stummschalten"
|
||||
|
||||
@ -145,25 +161,31 @@ msgstr "Importiere OPML-Datei"
|
||||
msgid "Rate RePod ❤️"
|
||||
msgstr "Bewerte RePod ❤️"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Sleep timer"
|
||||
msgstr "Einschlaftimer"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Minutes"
|
||||
msgstr "Minuten"
|
||||
|
||||
#, fuzzy
|
||||
msgid "%n min"
|
||||
msgid_plural "%n mins"
|
||||
msgstr[0] "%n min"
|
||||
msgstr[1] "%n mins"
|
||||
|
||||
#, fuzzy
|
||||
msgid "%n sec"
|
||||
msgid_plural "%n secs"
|
||||
msgstr[0] "%s sec"
|
||||
msgstr[1] "%n secs"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Playback speed"
|
||||
msgstr "Wiedergabegeschwindigkeit"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Favorite"
|
||||
msgstr "Favorit"
|
||||
|
||||
@ -173,6 +195,7 @@ msgstr "Bist Du sicher, dass Du das Abonnement löschen möchtest?"
|
||||
msgid "Error while removing the feed"
|
||||
msgstr "Fehler beim Löschen des Feeds"
|
||||
|
||||
#, fuzzy
|
||||
msgid "You can only have 10 favorites"
|
||||
msgstr "Du kannst nur 10 Favoriten haben"
|
||||
|
||||
@ -194,11 +217,14 @@ msgstr "Benötigte App fehlt"
|
||||
msgid "Install GPodder Sync"
|
||||
msgstr "Installiere GPodder Sync"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Pin some subscriptions to see their latest updates"
|
||||
msgstr "Pinne einige Abonnements, um ihre neuesten Updates zu sehen"
|
||||
|
||||
#, fuzzy
|
||||
msgid "No favorites"
|
||||
msgstr "Keine Favoriten"
|
||||
|
||||
#, fuzzy
|
||||
msgid "A browser extension conflict with RePod"
|
||||
msgstr "Ein Browser-Erweiterungskonflikt mit RePod"
|
||||
|
@ -62,6 +62,9 @@ msgstr ""
|
||||
msgid "Download"
|
||||
msgstr "Télécharger"
|
||||
|
||||
msgid "Skip to {match}"
|
||||
msgstr "Sauter à {match}"
|
||||
|
||||
msgid "Add a RSS link"
|
||||
msgstr "Ajouter un lien RSS"
|
||||
|
||||
|
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Nextcloud 3.14159\n"
|
||||
"Report-Msgid-Bugs-To: translations\\@example.com\n"
|
||||
"POT-Creation-Date: 2024-11-09 18:34+0000\n"
|
||||
"POT-Creation-Date: 2024-11-12 20:57+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@ -55,211 +55,215 @@ msgid ""
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:1
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:24
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:25
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:26
|
||||
msgid "Download"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:2
|
||||
msgid "Add a RSS link"
|
||||
msgid "Skip to {match}"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:3
|
||||
msgid "Add a RSS link"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:4
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:5
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:12
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:6
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:13
|
||||
msgid "Subscribe"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:6
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:13
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:7
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:14
|
||||
msgid "Error while adding the feed"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:7
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:8
|
||||
msgid "Could not fetch search results"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:8
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:9
|
||||
msgid "New podcasts"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:9
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:10
|
||||
msgid "Hot podcasts"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:10
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:11
|
||||
msgid "Could not fetch tops"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:11
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:12
|
||||
msgid "Copy feed"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:14
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:15
|
||||
msgid "Link copied to the clipboard"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:15
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:16
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:31
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:17
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:32
|
||||
msgid "Play"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:17
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:18
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:19
|
||||
msgid "Stop"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:19
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:20
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:21
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:22
|
||||
msgid "Read"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:22
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:23
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:24
|
||||
msgid "Open website"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:26
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:27
|
||||
msgid "Could not change the status of the episode"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:27
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:28
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:29
|
||||
msgid "Could not fetch episodes"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:29
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:30
|
||||
msgid "Rewind 10 seconds"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:30
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:31
|
||||
msgid "Pause"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:32
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:33
|
||||
msgid "Fast forward 30 seconds"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:33
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:34
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:35
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:36
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:36
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:37
|
||||
msgid "Unmute"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:37
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:38
|
||||
msgid "Export subscriptions"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:38
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:39
|
||||
msgid "Filtering episodes"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:39
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:40
|
||||
msgid "Show all"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:40
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:41
|
||||
msgid "Listened"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:41
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:42
|
||||
msgid "Listening"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:42
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:43
|
||||
msgid "Unlistened"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:43
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:44
|
||||
msgid "Import subscriptions"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:44
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:45
|
||||
msgid "Import OPML file"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:45
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:46
|
||||
msgid "Rate RePod ❤️"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:46
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:47
|
||||
msgid "Sleep timer"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:47
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:48
|
||||
msgid "Minutes"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:48
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:49
|
||||
msgid "%n min"
|
||||
msgid_plural "%n mins"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:49
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:50
|
||||
msgid "%n sec"
|
||||
msgid_plural "%n secs"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:50
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:51
|
||||
msgid "Playback speed"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:51
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:52
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:53
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:54
|
||||
msgid "Favorite"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:54
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:55
|
||||
msgid "Are you sure you want to delete this subscription?"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:55
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:56
|
||||
msgid "Error while removing the feed"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:56
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:57
|
||||
msgid "You can only have 10 favorites"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:57
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:58
|
||||
msgid "Add a podcast"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:58
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:59
|
||||
msgid "Could not fetch subscriptions"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:59
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:60
|
||||
msgid "Find a podcast"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:60
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:61
|
||||
msgid "Error loading feed"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:61
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:62
|
||||
msgid "Missing required app"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:62
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:63
|
||||
msgid "Install GPodder Sync"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:63
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:64
|
||||
msgid "Pin some subscriptions to see their latest updates"
|
||||
msgstr ""
|
||||
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:64
|
||||
#: /app/specialVueFakeDummyForL10nScript.js:65
|
||||
msgid "No favorites"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1,15 +1,15 @@
|
||||
{
|
||||
"extends": "@vue/tsconfig",
|
||||
"include": ["./src/**/*.ts", "./src/**/*.vue", "**/*.ts"],
|
||||
"compilerOptions": {
|
||||
"allowImportingTsExtensions": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Bundler",
|
||||
"noImplicitAny": false,
|
||||
"rootDir": ".",
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
}
|
||||
}
|
||||
"extends": "@vue/tsconfig",
|
||||
"include": ["./src/**/*.ts", "./src/**/*.vue", "**/*.ts"],
|
||||
"compilerOptions": {
|
||||
"allowImportingTsExtensions": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Bundler",
|
||||
"noImplicitAny": false,
|
||||
"rootDir": ".",
|
||||
"strict": true,
|
||||
"noEmit": true
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user