Compare commits

..

39 Commits
3.4.0 ... main

Author SHA1 Message Date
93a34ba991 Merge pull request 'chore(deps): update dependency @formatjs/intl-segmenter to ^11.7.4' (#202) from renovate/formatjs-intl-segmenter-11.x into main
All checks were successful
repod / xml (push) Successful in 23s
repod / php (push) Successful in 1m16s
repod / nodejs (push) Successful in 1m9s
repod / release (push) Has been skipped
Reviewed-on: #202
2024-11-18 08:26:19 +00:00
Renovate Bot
59807358c5 chore(deps): update dependency @formatjs/intl-segmenter to ^11.7.4
All checks were successful
repod / xml (push) Successful in 30s
repod / php (push) Successful in 1m14s
repod / nodejs (push) Successful in 1m20s
repod / release (push) Has been skipped
2024-11-18 07:00:27 +00:00
86276dcfcc Merge pull request 'chore(deps): update dependency vue to ^3.5.13' (#201) from renovate/vue-3.x into main
All checks were successful
repod / xml (push) Successful in 18s
repod / php (push) Successful in 1m14s
repod / nodejs (push) Successful in 1m15s
repod / release (push) Has been skipped
Reviewed-on: #201
2024-11-17 22:36:29 +00:00
Renovate Bot
aa043623f6 chore(deps): update dependency vue to ^3.5.13
All checks were successful
repod / xml (push) Successful in 15s
repod / php (push) Successful in 1m15s
repod / nodejs (push) Successful in 1m13s
repod / release (push) Has been skipped
2024-11-16 06:32:26 +00:00
4a82022cf0 Translated using Weblate (German)
All checks were successful
repod / xml (push) Successful in 27s
repod / php (push) Successful in 1m13s
repod / nodejs (push) Successful in 1m19s
repod / release (push) Has been skipped
Currently translated at 66.6% (36 of 54 strings)

Co-authored-by: Michel Roux <xefir@crystalyx.net>
Translate-URL: https://translate.crystalyx.net/projects/repod/gitea/de/
Translation: RePod/Gitea
2024-11-15 21:02:49 +00:00
879bd15f1d merge conflict with weblate
All checks were successful
repod / xml (push) Successful in 15s
repod / php (push) Successful in 1m11s
repod / nodejs (push) Successful in 1m17s
repod / release (push) Has been skipped
2024-11-15 09:48:06 +01:00
592e6b6b68 docs: 📝 rework the features in readme
All checks were successful
repod / xml (push) Successful in 2m14s
repod / php (push) Successful in 1m24s
repod / nodejs (push) Successful in 1m25s
repod / release (push) Has been skipped
2024-11-15 09:36:28 +01:00
c332dcd986 docs: 📝 lower image size to reduce readme size
All checks were successful
repod / xml (push) Successful in 15s
repod / php (push) Successful in 1m22s
repod / nodejs (push) Successful in 1m29s
repod / release (push) Has been skipped
2024-11-14 23:59:20 +01:00
28be29efae docs: 📝 lower image size to reduce readme size
Some checks failed
repod / nodejs (push) Waiting to run
repod / release (push) Waiting to run
repod / xml (push) Successful in 23s
repod / php (push) Has been cancelled
2024-11-14 23:57:38 +01:00
9c4db19b59 chore: 🌐 update translations
All checks were successful
repod / xml (push) Successful in 16s
repod / php (push) Successful in 1m23s
repod / nodejs (push) Successful in 1m16s
repod / release (push) Has been skipped
2024-11-14 23:24:43 +01:00
38e44b9731 fix: description is too large for title
All checks were successful
repod / xml (push) Successful in 17s
repod / php (push) Successful in 1m16s
repod / nodejs (push) Successful in 1m17s
repod / release (push) Has been skipped
2024-11-14 21:58:47 +01:00
26802b49a5 docs: 🌐 add note to participate on translations
All checks were successful
repod / xml (push) Successful in 16s
repod / php (push) Successful in 1m8s
repod / nodejs (push) Successful in 1m13s
repod / release (push) Has been skipped
2024-11-14 21:09:35 +01:00
d7dfb25062 docs: 🌐 credit original translation author
All checks were successful
repod / xml (push) Successful in 12s
repod / php (push) Successful in 1m10s
repod / nodejs (push) Successful in 1m20s
repod / release (push) Has been skipped
2024-11-14 20:54:48 +01:00
99977b1db4 Translated using Weblate (German)
Some checks failed
repod / release (push) Waiting to run
repod / xml (push) Successful in 1m54s
repod / php (push) Successful in 1m21s
repod / nodejs (push) Has been cancelled
Currently translated at 100.0% (54 of 54 strings)

Co-authored-by: Michel Roux <xefir@crystalyx.net>
Translate-URL: https://translate.crystalyx.net/projects/repod/gitea/de/
Translation: RePod/Gitea
2024-11-14 19:50:39 +00:00
230b646ceb docs: ✏️ fix typo on changelog
All checks were successful
repod / xml (push) Successful in 13s
repod / php (push) Successful in 1m9s
repod / nodejs (push) Successful in 1m10s
repod / release (push) Successful in 1m26s
2024-11-12 22:16:08 +01:00
06acea519c docs: 📝 better wording
All checks were successful
repod / xml (push) Successful in 10s
repod / php (push) Successful in 1m4s
repod / nodejs (push) Successful in 1m2s
repod / release (push) Has been skipped
2024-11-12 22:11:48 +01:00
f5c8689d50 docs: 📌 pin version 3.4.1
Some checks failed
repod / nodejs (push) Waiting to run
repod / release (push) Waiting to run
repod / xml (push) Successful in 12s
repod / php (push) Has been cancelled
2024-11-12 22:10:38 +01:00
e99b2c972d perf: 🌐 add title for accessibility on skip on modal
All checks were successful
repod / xml (push) Successful in 12s
repod / php (push) Successful in 1m6s
repod / nodejs (push) Successful in 1m6s
repod / release (push) Has been skipped
2024-11-12 22:02:18 +01:00
40ecea63d2 docs: 📝 chapter is supported now
All checks were successful
repod / xml (push) Successful in 12s
repod / php (push) Successful in 1m2s
repod / nodejs (push) Successful in 1m13s
repod / release (push) Has been skipped
2024-11-12 21:44:52 +01:00
e43adc79a1 feat: chapters based on timecodes in description (fix #69)
Some checks failed
repod / nodejs (push) Waiting to run
repod / release (push) Waiting to run
repod / xml (push) Successful in 22s
repod / php (push) Has been cancelled
2024-11-12 21:43:38 +01:00
eb6a4b2d9b fix: 🔒 lower security but fix #197
All checks were successful
repod / xml (push) Successful in 1m25s
repod / php (push) Successful in 1m10s
repod / nodejs (push) Successful in 1m16s
repod / release (push) Has been skipped
2024-11-12 20:10:19 +01:00
1d8ea08798 style: 🎨 add nextcloud/rector
All checks were successful
repod / xml (push) Successful in 22s
repod / php (push) Successful in 1m15s
repod / nodejs (push) Successful in 1m6s
repod / release (push) Has been skipped
2024-11-12 10:11:21 +01:00
7e6536c7ee Merge pull request 'chore(deps): update dependency dompurify to ^3.2.0' (#198) from renovate/dompurify-3.x into main
All checks were successful
repod / xml (push) Successful in 17s
repod / php (push) Successful in 1m15s
repod / nodejs (push) Successful in 1m20s
repod / release (push) Has been skipped
Reviewed-on: #198
2024-11-12 08:12:50 +00:00
Renovate Bot
c1a6d29362 chore(deps): update dependency dompurify to ^3.2.0
All checks were successful
repod / xml (push) Successful in 37s
repod / php (push) Successful in 1m46s
repod / nodejs (push) Successful in 1m12s
repod / release (push) Has been skipped
2024-11-12 06:43:17 +00:00
13969d5c03 Merge pull request 'chore(deps): update dependency vite to ^5.4.11' (#196) from renovate/vite-5.x into main
All checks were successful
repod / xml (push) Successful in 13s
repod / php (push) Successful in 1m7s
repod / nodejs (push) Successful in 1m2s
repod / release (push) Has been skipped
Reviewed-on: #196
2024-11-11 13:32:12 +00:00
Renovate Bot
ebf8b501e5 chore(deps): update dependency vite to ^5.4.11
All checks were successful
repod / xml (push) Successful in 11s
repod / php (push) Successful in 1m6s
repod / nodejs (push) Successful in 1m2s
repod / release (push) Has been skipped
2024-11-11 13:31:45 +00:00
e368baa0ee Actualiser renovate.json
All checks were successful
repod / xml (push) Successful in 19s
repod / php (push) Successful in 1m14s
repod / nodejs (push) Successful in 1m22s
repod / release (push) Has been skipped
2024-11-11 12:53:36 +00:00
a90fcceb7b style: 💄 make a gap between player's control
All checks were successful
repod / xml (push) Successful in 32s
repod / php (push) Successful in 1m14s
repod / nodejs (push) Successful in 1m32s
repod / release (push) Has been skipped
2024-11-10 22:53:50 +01:00
6c0976bc16 refactor: 👷 variabilize release dep
All checks were successful
repod / xml (push) Successful in 19s
repod / php (push) Successful in 1m14s
repod / nodejs (push) Successful in 1m16s
repod / release (push) Has been skipped
2024-11-10 19:25:05 +01:00
c439f8585e style: 📝 no need for huge comment block on makefile
All checks were successful
repod / xml (push) Successful in 16s
repod / php (push) Successful in 1m21s
repod / nodejs (push) Successful in 1m18s
repod / release (push) Has been skipped
2024-11-10 17:57:55 +01:00
d4e936b077 Merge pull request 'chore(deps): update dependency @vue/tsconfig to ^0.6.0' (#195) from renovate/vue-tsconfig-0.x into main
All checks were successful
repod / xml (push) Successful in 12s
repod / php (push) Successful in 1m18s
repod / nodejs (push) Successful in 1m13s
repod / release (push) Has been skipped
Reviewed-on: #195
2024-11-10 16:42:30 +00:00
Renovate Bot
ea8514016f chore(deps): update dependency @vue/tsconfig to ^0.6.0
All checks were successful
repod / xml (push) Successful in 15s
repod / php (push) Successful in 1m13s
repod / nodejs (push) Successful in 1m17s
repod / release (push) Has been skipped
2024-11-10 16:18:47 +00:00
c8fa87d03d style: 🎨 remove rule on php cs
All checks were successful
repod / xml (push) Successful in 13s
repod / php (push) Successful in 1m8s
repod / nodejs (push) Successful in 1m7s
repod / release (push) Has been skipped
2024-11-10 16:01:21 +01:00
b7e114f131 fix: 🔨 make dev stage app independant
All checks were successful
repod / xml (push) Successful in 12s
repod / php (push) Successful in 1m11s
repod / nodejs (push) Successful in 1m8s
repod / release (push) Has been skipped
2024-11-10 15:49:35 +01:00
a3879021e4 perf: remove vue-eslint-parser
All checks were successful
repod / xml (push) Successful in 13s
repod / php (push) Successful in 1m5s
repod / nodejs (push) Successful in 1m5s
repod / release (push) Has been skipped
2024-11-10 15:40:25 +01:00
07fd241b2a perf: remove ts-node
Some checks failed
repod / release (push) Waiting to run
repod / xml (push) Successful in 13s
repod / php (push) Successful in 1m11s
repod / nodejs (push) Has been cancelled
2024-11-10 15:38:02 +01:00
52bedda53d docs: 📝 add legend to links
All checks were successful
repod / xml (push) Successful in 10s
repod / php (push) Successful in 1m1s
repod / nodejs (push) Successful in 1m6s
repod / release (push) Has been skipped
2024-11-10 14:47:54 +01:00
f98cc71d60 docs: 📝 update comparaison table
All checks were successful
repod / xml (push) Successful in 11s
repod / php (push) Successful in 1m0s
repod / nodejs (push) Successful in 1m3s
repod / release (push) Has been skipped
2024-11-10 14:43:04 +01:00
25af5bdf54 feat: 🧑‍💻 add rector
All checks were successful
repod / xml (push) Successful in 11s
repod / php (push) Successful in 1m7s
repod / nodejs (push) Successful in 1m6s
repod / release (push) Has been skipped
2024-11-10 13:18:53 +01:00
42 changed files with 865 additions and 706 deletions

View File

@ -55,7 +55,7 @@ jobs:
- uses: akkuman/gitea-release-action@v1 - uses: akkuman/gitea-release-action@v1
with: with:
files: | files: |
build/artifacts/repod.tar.gz build/artifacts/${{ gitea.event.repository.name }}.tar.gz
- uses: FKLC/sign-files-action@v1.0.0 - uses: FKLC/sign-files-action@v1.0.0
with: with:
privateKey: ${{ secrets.PRIVATEKEY }} privateKey: ${{ secrets.PRIVATEKEY }}
@ -63,13 +63,13 @@ jobs:
extension: .sig extension: .sig
outputFolder: build/artifacts outputFolder: build/artifacts
files: | files: |
build/artifacts/repod.tar.gz build/artifacts/${{ gitea.event.repository.name }}.tar.gz
- id: sign - 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 - uses: actionsflow/axios@v1
with: with:
url: https://apps.nextcloud.com/api/v1/apps/releases url: https://apps.nextcloud.com/api/v1/apps/releases
method: POST method: POST
accept: 200,201 accept: 200,201
headers: '{ "Authorization": "Token <<<${{ secrets.TOKEN }}>>>" }' 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 }}>>>" }'

View File

@ -13,7 +13,6 @@ class MyConfig extends Config
$rules = parent::getRules(); $rules = parent::getRules();
$rules['@PhpCsFixer'] = true; $rules['@PhpCsFixer'] = true;
$rules['curly_braces_position']['classes_opening_brace'] = 'next_line_unless_newline_at_signature_end'; $rules['curly_braces_position']['classes_opening_brace'] = 'next_line_unless_newline_at_signature_end';
$rules['phpdoc_separation'] = false;
$rules['phpdoc_to_comment'] = false; $rules['phpdoc_to_comment'] = false;
return $rules; return $rules;
} }

View File

@ -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 ## 3.4.0 - Good Night - 2024-11-09
### Added ### Added

View File

@ -1,39 +1,4 @@
# https://github.com/nextcloud/appstore/blob/fixed-templates/nextcloudappstore/scaffolding/app-templates/26/app/Makefile # 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)) app_name=$(notdir $(CURDIR))
build_tools_directory=$(CURDIR)/build/tools build_tools_directory=$(CURDIR)/build/tools
@ -159,11 +124,11 @@ appstore:
# Start a nextcloud server on Docker to kickstart developement # Start a nextcloud server on Docker to kickstart developement
.PHONY: dev .PHONY: dev
dev: build dev: build
docker stop repod || true docker stop $(app_name) || true
docker rm repod || true docker rm $(app_name) || true
docker build -t repod . docker build -t $(app_name) .
docker run -itd --rm --name repod -v $(CURDIR):/var/www/html/apps/repod -p 80:80 repod docker run -itd --rm --name $(app_name) -v $(CURDIR):/var/www/html/apps/$(app_name) -p 80:80 $(app_name)
npm run watch npm run watch || docker stop $(app_name)
# Generate translations # Generate translations
.PHONY: l10n .PHONY: l10n

View File

@ -6,12 +6,12 @@ You need to have [GPodderSync](https://apps.nextcloud.com/apps/gpoddersync) inst
## Features ## Features
- Browse podcasts and play them directly in Nextcloud - 🔍 Browse and subscribe huge collection of podcasts
- Keep track of subscribed shows and episodes - 🔊 Listen to episodes directly in Nextcloud
- Sync them with GPodderSync compatible clients - 📋 Keep track of subscribed shows and episodes
- Import and export subscriptions - 🌐 Sync them with GPodderSync compatible clients
- Mobile friendly interface - 📱 Mobile friendly interface
- Unified search integration - 📡 Import and export your subscriptions
## Comparaison with similar apps for Nextcloud ## Comparaison with similar apps for Nextcloud
@ -19,37 +19,32 @@ You need to have [GPodderSync](https://apps.nextcloud.com/apps/gpoddersync) inst
| --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- |
| Actively maintened | ✅ | ✅ | ✅ | ❌ | | Actively maintened | ✅ | ✅ | ✅ | ❌ |
| Play your local music files | ❌ | ❌ | ✅ | ❌ | | 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 | ✅ | ❌ | ✅ | ✅ | | Add and manage subscriptions | ✅ | ❌ | ✅ | ✅ |
| Listen synced episodes by another clients | ✅ | ✅ | ❌ | ❌ | | Listen synced episodes by another clients | ✅ | ✅ | ❌ | ❌ |
| Fetch and listen new epidodes | ✅ | | ✅ | ✅ | | Fetch and listen new epidodes | ✅ | [](https://github.com/pbek/nextcloud-nextpod/issues/5) | ✅ | ✅ |
| Keep track of listened episodes | ✅ | ✅ | | ✅ | | Keep track of listened episodes | ✅ | ✅ | [](https://github.com/owncloud/music/issues/1148) | ✅ |
| Download epidodes | ✅ | ✅ | ❌ | ✅ | | 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 | ✅ | ❌ | ❌ | ✅ | | Search and discover new podcasts | ✅ | ❌ | ❌ | ✅ |
| Open episode website and RSS feed | ✅ | ✅ | ❌ | ✅ | | Open episode website and RSS feed | ✅ | ✅ | ❌ | ✅ |
| Integrate with Nextcloud search engine | ✅ | ❌ | ❌ | ✅ | | Integrate with Nextcloud search engine | ✅ | ❌ | ❌ | ✅ |
| Integrate with [Nextcloud Notes](https://apps.nextcloud.com/apps/notes) | ❌ | ✅ | ❌ | ❌ | | Integrate with [Nextcloud Notes](https://apps.nextcloud.com/apps/notes) | ❌ | ✅ | ❌ | ❌ |
| Mobile friendly interface | ✅ | ❌ | ✅ | ✅ | | Mobile friendly interface | ✅ | ❌ | ✅ | ✅ |
| Support chapters | ❌ | ❌ | ❌ | ✅ | | Support chapters | ✅ | ❌ | ❌ | ✅ |
| Available in multiple languages | ⭕ (en/fr/de) | ❌ | ✅ | ⭕ (en/de) | | 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 ## Screenshots
### Homepage <img src="./screens/index.png" width="230" title="Homepage" />
![homepage](./screens/index.png) <img src="./screens/discover.png" width="230" title="Discover" />
<img src="./screens/search.png" width="230" title="Search" />
### Discover <img src="./screens/episodes.png" width="230" title="Episode list" />
![homepage](./screens/discover.png) <img src="./screens/modal.png" width="230" title="Episode description" />
### Search
![search](./screens/search.png)
### Episode list
![episodes](./screens/episodes.png)
### Episode description
![modal](./screens/modal.png)
## Clients supporting sync of GPodderSync ## 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)) - 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 ## Credits
- [GPodder Sync](https://github.com/thrillfall/nextcloud-gpodder) for the database API - [GPodder Sync](https://github.com/thrillfall/nextcloud-gpodder) for the database API

View File

@ -14,7 +14,7 @@
## Requirements ## Requirements
You need to have [GPodderSync](https://apps.nextcloud.com/apps/gpoddersync) installed to use this app!]]></description> 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> <licence>agpl</licence>
<author mail="xefir@crystalyx.net" homepage="https://crystalyx.net">Michel Roux</author> <author mail="xefir@crystalyx.net" homepage="https://crystalyx.net">Michel Roux</author>
<namespace>RePod</namespace> <namespace>RePod</namespace>

View File

@ -12,12 +12,18 @@
"lint": "find . -name \\*.php -not -path './vendor/*' -not -path './vendor-bin/*' -not -path './build/*' -print0 | xargs -0 -n1 php -l", "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:check": "php-cs-fixer fix --dry-run --diff",
"cs:fix": "php-cs-fixer fix", "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": { "require-dev": {
"nextcloud/ocp": "^30.0.2", "nextcloud/ocp": "^30.0.2",
"roave/security-advisories": "dev-latest", "roave/security-advisories": "dev-latest",
"nextcloud/coding-standard": "^1.3.2", "nextcloud/coding-standard": "^1.3.2",
"nextcloud/rector": "^0.2.1",
"rector/rector": "^1.2.10",
"vimeo/psalm": "^5.26.1" "vimeo/psalm": "^5.26.1"
}, },
"config": { "config": {

253
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "2bded493404c793fc0cfceedfeccc38c", "content-hash": "a82f9b080077d3e1ddc2ee3a0c736cf4",
"packages": [], "packages": [],
"packages-dev": [ "packages-dev": [
{ {
@ -169,16 +169,16 @@
}, },
{ {
"name": "composer/pcre", "name": "composer/pcre",
"version": "3.3.1", "version": "3.3.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/composer/pcre.git", "url": "https://github.com/composer/pcre.git",
"reference": "63aaeac21d7e775ff9bc9d45021e1745c97521c4" "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/composer/pcre/zipball/63aaeac21d7e775ff9bc9d45021e1745c97521c4", "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e",
"reference": "63aaeac21d7e775ff9bc9d45021e1745c97521c4", "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -188,8 +188,8 @@
"phpstan/phpstan": "<1.11.10" "phpstan/phpstan": "<1.11.10"
}, },
"require-dev": { "require-dev": {
"phpstan/phpstan": "^1.11.10", "phpstan/phpstan": "^1.12 || ^2",
"phpstan/phpstan-strict-rules": "^1.1", "phpstan/phpstan-strict-rules": "^1 || ^2",
"phpunit/phpunit": "^8 || ^9" "phpunit/phpunit": "^8 || ^9"
}, },
"type": "library", "type": "library",
@ -228,7 +228,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/composer/pcre/issues", "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": [ "funding": [
{ {
@ -244,7 +244,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-08-27T18:44:43+00:00" "time": "2024-11-12T16:29:46+00:00"
}, },
{ {
"name": "composer/semver", "name": "composer/semver",
@ -822,6 +822,68 @@
}, },
"time": "2024-10-19T00:42:39+00:00" "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", "name": "nikic/php-parser",
"version": "v4.19.4", "version": "v4.19.4",
@ -985,16 +1047,16 @@
}, },
{ {
"name": "phpdocumentor/reflection-docblock", "name": "phpdocumentor/reflection-docblock",
"version": "5.5.1", "version": "5.6.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "0c70d2c566e899666f367ab7b80986beb3581e6f" "reference": "f3558a4c23426d12bffeaab463f8a8d8b681193c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/0c70d2c566e899666f367ab7b80986beb3581e6f", "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/f3558a4c23426d12bffeaab463f8a8d8b681193c",
"reference": "0c70d2c566e899666f367ab7b80986beb3581e6f", "reference": "f3558a4c23426d12bffeaab463f8a8d8b681193c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1003,7 +1065,7 @@
"php": "^7.4 || ^8.0", "php": "^7.4 || ^8.0",
"phpdocumentor/reflection-common": "^2.2", "phpdocumentor/reflection-common": "^2.2",
"phpdocumentor/type-resolver": "^1.7", "phpdocumentor/type-resolver": "^1.7",
"phpstan/phpdoc-parser": "^1.7", "phpstan/phpdoc-parser": "^1.7|^2.0",
"webmozart/assert": "^1.9.1" "webmozart/assert": "^1.9.1"
}, },
"require-dev": { "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.", "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
"support": { "support": {
"issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", "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", "name": "phpdocumentor/type-resolver",
"version": "1.9.0", "version": "1.10.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpDocumentor/TypeResolver.git", "url": "https://github.com/phpDocumentor/TypeResolver.git",
"reference": "1fb5ba8d045f5dd984ebded5b1cc66f29459422d" "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/1fb5ba8d045f5dd984ebded5b1cc66f29459422d", "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/679e3ce485b99e84c775d28e2e96fade9a7fb50a",
"reference": "1fb5ba8d045f5dd984ebded5b1cc66f29459422d", "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"doctrine/deprecations": "^1.0", "doctrine/deprecations": "^1.0",
"php": "^7.3 || ^8.0", "php": "^7.3 || ^8.0",
"phpdocumentor/reflection-common": "^2.0", "phpdocumentor/reflection-common": "^2.0",
"phpstan/phpdoc-parser": "^1.18" "phpstan/phpdoc-parser": "^1.18|^2.0"
}, },
"require-dev": { "require-dev": {
"ext-tokenizer": "*", "ext-tokenizer": "*",
@ -1101,36 +1163,36 @@
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
"support": { "support": {
"issues": "https://github.com/phpDocumentor/TypeResolver/issues", "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", "name": "phpstan/phpdoc-parser",
"version": "1.33.0", "version": "2.0.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git", "url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "82a311fd3690fb2bf7b64d5c98f912b3dd746140" "reference": "c00d78fb6b29658347f9d37ebe104bffadf36299"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/82a311fd3690fb2bf7b64d5c98f912b3dd746140", "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/c00d78fb6b29658347f9d37ebe104bffadf36299",
"reference": "82a311fd3690fb2bf7b64d5c98f912b3dd746140", "reference": "c00d78fb6b29658347f9d37ebe104bffadf36299",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^7.2 || ^8.0" "php": "^7.4 || ^8.0"
}, },
"require-dev": { "require-dev": {
"doctrine/annotations": "^2.0", "doctrine/annotations": "^2.0",
"nikic/php-parser": "^4.15", "nikic/php-parser": "^5.3.0",
"php-parallel-lint/php-parallel-lint": "^1.2", "php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/extension-installer": "^1.0", "phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^1.5", "phpstan/phpstan": "^2.0",
"phpstan/phpstan-phpunit": "^1.1", "phpstan/phpstan-phpunit": "^2.0",
"phpstan/phpstan-strict-rules": "^1.0", "phpstan/phpstan-strict-rules": "^2.0",
"phpunit/phpunit": "^9.5", "phpunit/phpunit": "^9.6",
"symfony/process": "^5.2" "symfony/process": "^5.2"
}, },
"type": "library", "type": "library",
@ -1148,9 +1210,67 @@
"description": "PHPDoc parser with support for nullable, intersection and generic types", "description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": { "support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues", "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", "name": "psr/clock",
@ -1353,6 +1473,65 @@
}, },
"time": "2021-07-14T16:41:46+00:00" "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", "name": "roave/security-advisories",
"version": "dev-latest", "version": "dev-latest",
@ -3219,7 +3398,9 @@
}, },
"prefer-stable": false, "prefer-stable": false,
"prefer-lowest": false, "prefer-lowest": false,
"platform": {}, "platform": {
"php": "^8.1"
},
"platform-dev": {}, "platform-dev": {},
"platform-overrides": { "platform-overrides": {
"php": "8.1" "php": "8.1"

View File

@ -5,8 +5,9 @@ OC.L10N.register(
"Podcast" : "Podcast", "Podcast" : "Podcast",
"RePod" : "RePod", "RePod" : "RePod",
"🔊 Browse, manage and listen to podcasts" : "🔊 Suchen, Verwalten und Anhören von Podcasts", "🔊 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", "Download" : "Herunterladen",
"Skip to {match}" : "Springen zu {match}",
"Add a RSS link" : "Einen RSS-Link hinzufügen", "Add a RSS link" : "Einen RSS-Link hinzufügen",
"Subscribe" : "Abonnieren", "Subscribe" : "Abonnieren",
"Error while adding the feed" : "Fehler beim Hinzufügen des Feeds", "Error while adding the feed" : "Fehler beim Hinzufügen des Feeds",
@ -55,4 +56,4 @@ OC.L10N.register(
"No favorites" : "Keine Favoriten", "No favorites" : "Keine Favoriten",
"A browser extension conflict with RePod" : "Ein Browser-Erweiterungskonflikt mit RePod" "A browser extension conflict with RePod" : "Ein Browser-Erweiterungskonflikt mit RePod"
}, },
""); "nplurals=2; plural=n != 1;");

View File

@ -3,8 +3,9 @@
"Podcast" : "Podcast", "Podcast" : "Podcast",
"RePod" : "RePod", "RePod" : "RePod",
"🔊 Browse, manage and listen to podcasts" : "🔊 Suchen, Verwalten und Anhören von Podcasts", "🔊 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", "Download" : "Herunterladen",
"Skip to {match}" : "Springen zu {match}",
"Add a RSS link" : "Einen RSS-Link hinzufügen", "Add a RSS link" : "Einen RSS-Link hinzufügen",
"Subscribe" : "Abonnieren", "Subscribe" : "Abonnieren",
"Error while adding the feed" : "Fehler beim Hinzufügen des Feeds", "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", "Pin some subscriptions to see their latest updates" : "Pinne einige Abonnements, um ihre neuesten Updates zu sehen",
"No favorites" : "Keine Favoriten", "No favorites" : "Keine Favoriten",
"A browser extension conflict with RePod" : "Ein Browser-Erweiterungskonflikt mit RePod" "A browser extension conflict with RePod" : "Ein Browser-Erweiterungskonflikt mit RePod"
},"pluralForm" :"" },"pluralForm" :"nplurals=2; plural=n != 1;"
} }

View File

@ -7,6 +7,7 @@ OC.L10N.register(
"🔊 Browse, manage and listen to podcasts" : "🔊 Parcourir, gérer et écouter vos podcasts", "🔊 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 !", "## 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", "Download" : "Télécharger",
"Skip to {match}" : "Sauter à {match}",
"Add a RSS link" : "Ajouter un lien RSS", "Add a RSS link" : "Ajouter un lien RSS",
"Subscribe" : "S'abonner", "Subscribe" : "S'abonner",
"Error while adding the feed" : "Erreur lors de l'ajout du flux", "Error while adding the feed" : "Erreur lors de l'ajout du flux",

View File

@ -5,6 +5,7 @@
"🔊 Browse, manage and listen to podcasts" : "🔊 Parcourir, gérer et écouter vos podcasts", "🔊 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 !", "## 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", "Download" : "Télécharger",
"Skip to {match}" : "Sauter à {match}",
"Add a RSS link" : "Ajouter un lien RSS", "Add a RSS link" : "Ajouter un lien RSS",
"Subscribe" : "S'abonner", "Subscribe" : "S'abonner",
"Error while adding the feed" : "Erreur lors de l'ajout du flux", "Error while adding the feed" : "Erreur lors de l'ajout du flux",

View File

@ -16,6 +16,7 @@ use OCP\AppFramework\Services\IInitialState;
class Application extends App implements IBootstrap class Application extends App implements IBootstrap
{ {
public const APP_ID = 'repod'; public const APP_ID = 'repod';
private const GPODDERSYNC_ID = 'gpoddersync'; private const GPODDERSYNC_ID = 'gpoddersync';
public function __construct() { public function __construct() {
@ -40,7 +41,7 @@ class Application extends App implements IBootstrap
if (!$gpoddersync) { if (!$gpoddersync) {
try { try {
$appManager->enableApp(self::GPODDERSYNC_ID); $appManager->enableApp(self::GPODDERSYNC_ID);
} catch (AppPathNotFoundException $e) { } catch (AppPathNotFoundException) {
} }
} }

View File

@ -22,10 +22,10 @@ class EpisodesController extends Controller
{ {
public function __construct( public function __construct(
IRequest $request, IRequest $request,
private EpisodeActionReader $episodeActionReader, private readonly EpisodeActionReader $episodeActionReader,
private EpisodeActionRepository $episodeActionRepository, private readonly EpisodeActionRepository $episodeActionRepository,
private IClientService $clientService, private readonly IClientService $clientService,
private UserService $userService private readonly UserService $userService
) { ) {
parent::__construct(Application::APP_ID, $request); parent::__construct(Application::APP_ID, $request);
} }
@ -37,8 +37,8 @@ class EpisodesController extends Controller
$client = $this->clientService->newClient(); $client = $this->clientService->newClient();
$feed = $client->get($url); $feed = $client->get($url);
$episodes = $this->episodeActionReader->parseRssXml((string) $feed->getBody()); $episodes = $this->episodeActionReader->parseRssXml((string) $feed->getBody());
usort($episodes, fn (EpisodeActionExtraData $a, EpisodeActionExtraData $b) => $b->getPubDate() <=> $a->getPubDate()); 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) => $episode->getGuid(), $episodes)))); $episodes = array_values(array_intersect_key($episodes, array_unique(array_map(fn (EpisodeActionExtraData $episode): string => $episode->getGuid(), $episodes))));
return new JSONResponse($episodes, $feed->getStatusCode()); return new JSONResponse($episodes, $feed->getStatusCode());
} }

View File

@ -22,11 +22,11 @@ class OpmlController extends Controller
{ {
public function __construct( public function __construct(
IRequest $request, IRequest $request,
private IL10N $l10n, private readonly IL10N $l10n,
private PodcastDataReader $podcastDataReader, private readonly PodcastDataReader $podcastDataReader,
private PodcastMetricsReader $podcastMetricsReader, private readonly PodcastMetricsReader $podcastMetricsReader,
private SubscriptionChangeSaver $subscriptionChangeSaver, private readonly SubscriptionChangeSaver $subscriptionChangeSaver,
private UserService $userService private readonly UserService $userService
) { ) {
parent::__construct(Application::APP_ID, $request); parent::__construct(Application::APP_ID, $request);
} }
@ -55,7 +55,7 @@ class OpmlController extends Controller
foreach ($subscriptions as $subscription) { foreach ($subscriptions as $subscription) {
try { try {
$podcast = $this->podcastDataReader->getCachedOrFetchPodcastData($subscription->getUrl(), $this->userService->getUserUID()); $podcast = $this->podcastDataReader->getCachedOrFetchPodcastData($subscription->getUrl(), $this->userService->getUserUID());
} catch (\Exception $e) { } catch (\Exception) {
continue; continue;
} }

View File

@ -11,15 +11,13 @@ use OCP\AppFramework\Http\Attribute\NoAdminRequired;
use OCP\AppFramework\Http\Attribute\NoCSRFRequired; use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
use OCP\AppFramework\Http\ContentSecurityPolicy; use OCP\AppFramework\Http\ContentSecurityPolicy;
use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Http\TemplateResponse;
use OCP\IConfig;
use OCP\IRequest; use OCP\IRequest;
use OCP\Util; use OCP\Util;
class PageController extends Controller class PageController extends Controller
{ {
public function __construct( public function __construct(
IRequest $request, IRequest $request
private IConfig $config
) { ) {
parent::__construct(Application::APP_ID, $request); parent::__construct(Application::APP_ID, $request);
} }

View File

@ -20,9 +20,9 @@ class PodcastController extends Controller
{ {
public function __construct( public function __construct(
IRequest $request, IRequest $request,
private ICacheFactory $cacheFactory, private readonly ICacheFactory $cacheFactory,
private IClientService $clientService, private readonly IClientService $clientService,
private PodcastDataReader $podcastDataReader private readonly PodcastDataReader $podcastDataReader
) { ) {
parent::__construct(Application::APP_ID, $request); parent::__construct(Application::APP_ID, $request);
} }
@ -36,7 +36,7 @@ class PodcastController extends Controller
if ($this->cacheFactory->isLocalCacheAvailable()) { if ($this->cacheFactory->isLocalCacheAvailable()) {
try { try {
$podcast = $this->podcastDataReader->tryGetCachedPodcastData($url); $podcast = $this->podcastDataReader->tryGetCachedPodcastData($url);
} catch (\Exception $e) { } catch (\Exception) {
} }
} }
@ -51,7 +51,7 @@ class PodcastController extends Controller
if ($this->cacheFactory->isLocalCacheAvailable()) { if ($this->cacheFactory->isLocalCacheAvailable()) {
try { try {
$this->podcastDataReader->trySetCachedPodcastData($url, $podcast); $this->podcastDataReader->trySetCachedPodcastData($url, $podcast);
} catch (\Exception $e) { } catch (\Exception) {
} }
} }

View File

@ -17,7 +17,7 @@ class SearchController extends Controller
{ {
public function __construct( public function __construct(
IRequest $request, IRequest $request,
private MultiPodService $multiPodService private readonly MultiPodService $multiPodService
) { ) {
parent::__construct(Application::APP_ID, $request); parent::__construct(Application::APP_ID, $request);
} }

View File

@ -17,7 +17,7 @@ class ToplistController extends Controller
{ {
public function __construct( public function __construct(
IRequest $request, IRequest $request,
private FyydService $fyydService private readonly FyydService $fyydService
) { ) {
parent::__construct(Application::APP_ID, $request); parent::__construct(Application::APP_ID, $request);
} }

View File

@ -28,22 +28,22 @@ use OCA\GPodderSync\Core\EpisodeAction\EpisodeAction;
* action: ?EpisodeActionType * action: ?EpisodeActionType
* } * }
*/ */
class EpisodeActionExtraData implements \JsonSerializable class EpisodeActionExtraData implements \JsonSerializable, \Stringable
{ {
public function __construct( public function __construct(
private string $title, private readonly string $title,
private ?string $url, private readonly ?string $url,
private string $name, private readonly string $name,
private ?string $link, private readonly ?string $link,
private ?string $image, private readonly ?string $image,
private ?string $description, private readonly ?string $description,
private int $fetchedAtUnix, private readonly int $fetchedAtUnix,
private string $guid, private readonly string $guid,
private ?string $type, private readonly ?string $type,
private ?int $size, private readonly ?int $size,
private ?\DateTime $pubDate, private readonly ?\DateTime $pubDate,
private ?string $duration, private readonly ?string $duration,
private ?EpisodeAction $action private readonly ?EpisodeAction $action
) {} ) {}
public function __toString(): string { public function __toString(): string {
@ -120,7 +120,7 @@ class EpisodeActionExtraData implements \JsonSerializable
'size' => $this->size, 'size' => $this->size,
'pubDate' => $this->pubDate, 'pubDate' => $this->pubDate,
'duration' => $this->duration, 'duration' => $this->duration,
'action' => $this->action ? $this->action->toArray() : null, 'action' => $this->action instanceof EpisodeAction ? $this->action->toArray() : null,
]; ];
} }

View File

@ -11,8 +11,8 @@ use OCA\RePod\Service\UserService;
class EpisodeActionReader extends CoreEpisodeActionReader class EpisodeActionReader extends CoreEpisodeActionReader
{ {
public function __construct( public function __construct(
private EpisodeActionRepository $episodeActionRepository, private readonly EpisodeActionRepository $episodeActionRepository,
private UserService $userService 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. * Specs : https://github.com/Podcast-Standards-Project/PSP-1-Podcast-RSS-Specification/blob/main/README.md.
* *
* @return EpisodeActionExtraData[] * @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 { public function parseRssXml(string $xmlString, ?int $fetchedAtUnix = null): array {
$episodes = []; $episodes = [];
@ -92,9 +93,6 @@ class EpisodeActionReader extends CoreEpisodeActionReader
$description = $this->stringOrNull($iTunesItemChildren->summary); $description = $this->stringOrNull($iTunesItemChildren->summary);
} }
// Remove tags
$description = strip_tags(str_replace(['<br>', '<br/>', '<br />'], "\n", $description ?? ''));
// Get episode duration // Get episode duration
if (isset($iTunesItemChildren)) { if (isset($iTunesItemChildren)) {
$duration = $this->stringOrNull($iTunesItemChildren->duration); $duration = $this->stringOrNull($iTunesItemChildren->duration);
@ -107,7 +105,7 @@ class EpisodeActionReader extends CoreEpisodeActionReader
if (isset($pubDate)) { if (isset($pubDate)) {
try { try {
$pubDate = new \DateTime($pubDate); $pubDate = new \DateTime($pubDate);
} catch (\Exception $e) { } catch (\Exception) {
$pubDate = null; $pubDate = null;
} }
} }

View File

@ -13,9 +13,9 @@ class FyydService implements IPodProvider
private const BASE_URL = 'https://api.fyyd.de/0.2/'; private const BASE_URL = 'https://api.fyyd.de/0.2/';
public function __construct( public function __construct(
private IClientService $clientService, private readonly IClientService $clientService,
private LoggerInterface $logger, private readonly LoggerInterface $logger,
private UserService $userService private readonly UserService $userService
) {} ) {}
public function search(string $value): array { public function search(string $value): array {
@ -94,8 +94,8 @@ class FyydService implements IPodProvider
if (array_key_exists('data', $langJson) && is_array($langJson['data'])) { if (array_key_exists('data', $langJson) && is_array($langJson['data'])) {
$language = in_array($userLang, $langJson['data']) ? $userLang : 'en'; $language = in_array($userLang, $langJson['data']) ? $userLang : 'en';
} }
} catch (\Exception $e) { } catch (\Exception $exception) {
$this->logger->error($e->getMessage(), $e->getTrace()); $this->logger->error($exception->getMessage(), $exception->getTrace());
} }
$podcastClient = $this->clientService->newClient(); $podcastClient = $this->clientService->newClient();

View File

@ -12,8 +12,8 @@ class ItunesService implements IPodProvider
private const BASE_URL = 'https://itunes.apple.com/'; private const BASE_URL = 'https://itunes.apple.com/';
public function __construct( public function __construct(
private IClientService $clientService, private readonly IClientService $clientService,
private UserService $userService private readonly UserService $userService
) {} ) {}
public function search(string $value): array { public function search(string $value): array {

View File

@ -17,7 +17,7 @@ class MultiPodService implements IPodProvider
public function __construct( public function __construct(
FyydService $fyydService, FyydService $fyydService,
ItunesService $itunesService, ItunesService $itunesService,
private LoggerInterface $logger private readonly LoggerInterface $logger
) { ) {
$this->providers = [$fyydService, $itunesService]; $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( return array_values(
array_intersect_key( array_intersect_key(

View File

@ -16,9 +16,9 @@ use OCP\Search\SearchResultEntry;
class SearchProvider implements IProvider class SearchProvider implements IProvider
{ {
public function __construct( public function __construct(
private IL10N $l10n, private readonly IL10N $l10n,
private IURLGenerator $urlGenerator, private readonly IURLGenerator $urlGenerator,
private MultiPodService $multiPodService private readonly MultiPodService $multiPodService
) {} ) {}
public function getId(): string { public function getId(): string {
@ -30,7 +30,7 @@ class SearchProvider implements IProvider
} }
public function getOrder(string $route, array $routeParameters): int { 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 // Active app, prefer my results
return -1; return -1;
} }

View File

@ -10,8 +10,8 @@ use OCP\L10N\IFactory;
class UserService class UserService
{ {
public function __construct( public function __construct(
private IFactory $l10n, private readonly IFactory $l10n,
private IUserSession $userSession private readonly IUserSession $userSession
) {} ) {}
public function getUserUID(): string { public function getUserUID(): string {
@ -27,7 +27,7 @@ class UserService
public function getCountryCode(): string { public function getCountryCode(): string {
$isoCodes = explode('_', $this->getIsoCode()); $isoCodes = explode('_', $this->getIsoCode());
return isset($isoCodes[1]) ? $isoCodes[1] : 'us'; return $isoCodes[1] ?? 'us';
} }
public function getLangCode(): string { public function getLangCode(): string {

736
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,33 +1,34 @@
{ {
"name": "repod", "name": "repod",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"type": "module",
"scripts": { "scripts": {
"build": "vue-tsc && vite build", "build": "vite build",
"dev": "vite --mode development build", "dev": "vite --mode development build",
"watch": "vite --mode development build --watch",
"lint": "vue-tsc && eslint src", "lint": "vue-tsc && eslint src",
"lint:fix": "vue-tsc && eslint src --fix", "lint:fix": "vue-tsc && eslint src --fix",
"stylelint": "stylelint src/**/*.vue src/**/*.scss src/**/*.css", "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": [ "browserslist": [
"extends @nextcloud/browserslist-config" "extends @nextcloud/browserslist-config"
], ],
"prettier": "@nextcloud/prettier-config",
"dependencies": { "dependencies": {
"@formatjs/intl-segmenter": "^11.7.3", "@formatjs/intl-segmenter": "^11.7.4",
"@nextcloud/axios": "^2.5.1", "@nextcloud/axios": "^2.5.1",
"@nextcloud/initial-state": "^2.2.0", "@nextcloud/initial-state": "^2.2.0",
"@nextcloud/l10n": "^3.1.0", "@nextcloud/l10n": "^3.1.0",
"@nextcloud/router": "^3.0.1", "@nextcloud/router": "^3.0.1",
"@nextcloud/vite-config": "^2.2.2", "@nextcloud/vite-config": "^2.2.2",
"@nextcloud/vue": "9.0.0-alpha.5", "@nextcloud/vue": "9.0.0-alpha.5",
"dompurify": "^3.1.7", "dompurify": "^3.2.0",
"linkify-html": "^4.1.3", "linkify-html": "^4.1.3",
"pinia": "^2.2.6", "pinia": "^2.2.6",
"toastify-js": "^1.12.0", "toastify-js": "^1.12.0",
"vite": "^5.4.10", "vite": "^5.4.11",
"vue": "^3.5.12", "vue": "^3.5.13",
"vue-material-design-icons": "^5.3.1", "vue-material-design-icons": "^5.3.1",
"vue-router": "^4.4.5" "vue-router": "^4.4.5"
}, },
@ -38,14 +39,11 @@
"@nextcloud/stylelint-config": "^3.0.1", "@nextcloud/stylelint-config": "^3.0.1",
"@types/toastify-js": "^1.12.3", "@types/toastify-js": "^1.12.3",
"@vue/eslint-config-typescript": "^13", "@vue/eslint-config-typescript": "^13",
"@vue/tsconfig": "^0.5.1", "@vue/tsconfig": "^0.6.0",
"eslint-config-prettier": "^9.1.0", "eslint-config-prettier": "^9.1.0",
"eslint-plugin-pinia": "^0.4.1", "eslint-plugin-pinia": "^0.4.1",
"eslint-plugin-prettier": "^5.2.1", "eslint-plugin-prettier": "^5.2.1",
"ts-node": "^10.9.2",
"typescript": "5.5", "typescript": "5.5",
"vue-eslint-parser": "^9.4.3",
"vue-tsc": "^2.1.10" "vue-tsc": "^2.1.10"
}, }
"prettier": "@nextcloud/prettier-config"
} }

34
rector.php Normal file
View 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,
)
;

View File

@ -1,3 +1,4 @@
{ {
"$schema": "https://docs.renovatebot.com/renovate-schema.json" "$schema": "https://docs.renovatebot.com/renovate-schema.json",
"rangeStrategy": "bump"
} }

View File

@ -1,22 +1,44 @@
<template> <template>
<div v-sanitize="source" class="html" /> <div ref="html" v-sanitize="source" class="html" />
</template> </template>
<script lang="ts"> <script lang="ts">
import dompurify from 'dompurify' import dompurify from 'dompurify'
import linkifyHtml from 'linkify-html' 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 { export default {
name: 'SafeHtml', name: 'SafeHtml',
directives: { directives: {
sanitize: { sanitize: {
mounted(el, binding) { mounted(el, binding) {
el.innerHTML = dompurify.sanitize( el.innerHTML = dompurify
linkifyHtml(binding.value, { .sanitize(
nl2br: true, linkifyHtml(binding.value, {
target: '_blank', 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, 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> </script>
<style> <style>
.html a { .html a,
seekable {
cursor: pointer;
text-decoration: underline; text-decoration: underline;
} }
</style> </style>

View File

@ -11,7 +11,6 @@
:name="episode.name" :name="episode.name"
:one-line="oneLine" :one-line="oneLine"
:style="{ opacity: hasEnded(episode) ? 0.4 : 1 }" :style="{ opacity: hasEnded(episode) ? 0.4 : 1 }"
:title="episode.description"
@click="modalEpisode = episode"> @click="modalEpisode = episode">
<template #actions> <template #actions>
<NcActionButton <NcActionButton

View File

@ -55,6 +55,7 @@ export default {
<style scoped> <style scoped>
.controls { .controls {
display: flex; display: flex;
gap: 0.5rem;
} }
.pointer { .pointer {

View File

@ -51,3 +51,16 @@ export const durationToSeconds = (duration: string): number => {
seconds += splitDuration.length > 2 ? parseInt(splitDuration[2]) * 60 * 60 : 0 seconds += splitDuration.length > 2 ? parseInt(splitDuration[2]) * 60 * 60 : 0
return seconds 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

View File

@ -7,8 +7,10 @@ namespace OCA\GPodderSync\Core\EpisodeAction;
class EpisodeActionReader class EpisodeActionReader
{ {
/** /**
* @param array $episodeActionsArray [] * @param array $episodeActionsArray []
*
* @return EpisodeAction[] * @return EpisodeAction[]
*
* @throws \InvalidArgumentException * @throws \InvalidArgumentException
*/ */
public function fromArray(array $episodeActionsArray) {} public function fromArray(array $episodeActionsArray) {}

View File

@ -29,7 +29,8 @@ class PodcastData implements \JsonSerializable
/** /**
* @return PodcastData * @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) {} public static function parseRssXml(string $xmlString, ?int $fetchedAtUnix = null) {}
@ -81,7 +82,8 @@ class PodcastData implements \JsonSerializable
public function jsonSerialize(): mixed {} public function jsonSerialize(): mixed {}
/** /**
* @param PodcastDataType $data * @param PodcastDataType $data
*
* @return PodcastData * @return PodcastData
*/ */
public static function fromArray(array $data) {} public static function fromArray(array $data) {}

View File

@ -21,6 +21,7 @@ class EpisodeActionMapper extends QBMapper
/** /**
* @return EpisodeActionEntity[] * @return EpisodeActionEntity[]
*
* @throws Exception * @throws Exception
*/ */
public function findAll(int $sinceTimestamp, string $userId) {} public function findAll(int $sinceTimestamp, string $userId) {}

View File

@ -14,12 +14,14 @@ class EpisodeActionWriter
/** /**
* @return EpisodeActionEntity * @return EpisodeActionEntity
*
* @throws Exception * @throws Exception
*/ */
public function save(EpisodeActionEntity $episodeActionEntity) {} public function save(EpisodeActionEntity $episodeActionEntity) {}
/** /**
* @return EpisodeActionEntity * @return EpisodeActionEntity
*
* @throws Exception * @throws Exception
*/ */
public function update(EpisodeActionEntity $episodeActionEntity) {} public function update(EpisodeActionEntity $episodeActionEntity) {}

View File

@ -1,20 +1,22 @@
# SOME DESCRIPTIVE TITLE. # SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the Nextcloud package. # This file is distributed under the same license as the Nextcloud package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # OiledAmoeba <florian+crystalyx@ruhnke.cloud>, 2024.
# # Michel Roux <xefir@crystalyx.net>, 2024.
#, fuzzy
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Nextcloud 3.14159\n" "Project-Id-Version: Nextcloud 3.14159\n"
"Report-Msgid-Bugs-To: translations\\@example.com\n" "Report-Msgid-Bugs-To: translations\\@example.com\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: 2024-11-15 21:02+0000\n"
"Last-Translator: OiledAmoeba <florian+crystalyx@ruhnke.cloud>\n" "Last-Translator: Michel Roux <xefir@crystalyx.net>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: German <https://translate.crystalyx.net/projects/repod/gitea/"
"de/>\n"
"Language: de\n" "Language: de\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.8.3\n"
msgid "RePod Subscriptions" msgid "RePod Subscriptions"
msgstr "RePod Abonnements" msgstr "RePod Abonnements"
@ -28,6 +30,7 @@ msgstr "RePod"
msgid "🔊 Browse, manage and listen to podcasts" msgid "🔊 Browse, manage and listen to podcasts"
msgstr "🔊 Suchen, Verwalten und Anhören von Podcasts" msgstr "🔊 Suchen, Verwalten und Anhören von Podcasts"
#, fuzzy
msgid "" msgid ""
"## Features\n" "## Features\n"
"- 🔍 Browse and subscribe huge collection of podcasts\n" "- 🔍 Browse and subscribe huge collection of podcasts\n"
@ -47,9 +50,12 @@ msgstr ""
"## Funktionen\n" "## Funktionen\n"
"- 🔍 Durchsuchen und abonnieren einer großen Sammlung von Podcasts\n" "- 🔍 Durchsuchen und abonnieren einer großen Sammlung von Podcasts\n"
"- 🔊 Episoden direkt in Nextcloud anhören\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" "- 📱 Mobile-freundliche Schnittstelle\n"
"- 📡 Importieren und Exportieren Ihrer Abonnements\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" "\n"
"## Voraussetzungen\n" "## Voraussetzungen\n"
"Du musst [GPodderSync](https://apps.nextcloud.com/apps/gpoddersync) " "Du musst [GPodderSync](https://apps.nextcloud.com/apps/gpoddersync) "
@ -58,6 +64,10 @@ msgstr ""
msgid "Download" msgid "Download"
msgstr "Herunterladen" msgstr "Herunterladen"
#, fuzzy
msgid "Skip to {match}"
msgstr "Springen zu {match}"
msgid "Add a RSS link" msgid "Add a RSS link"
msgstr "Einen RSS-Link hinzufügen" msgstr "Einen RSS-Link hinzufügen"
@ -82,6 +92,7 @@ msgstr "Titel können nicht abgerufen werden"
msgid "Copy feed" msgid "Copy feed"
msgstr "Feed kopieren" msgstr "Feed kopieren"
#, fuzzy
msgid "Link copied to the clipboard" msgid "Link copied to the clipboard"
msgstr "Der Link des Feeds wurde in die Zwischenablage kopiert" msgstr "Der Link des Feeds wurde in die Zwischenablage kopiert"
@ -91,6 +102,7 @@ msgstr "Abspielen"
msgid "Stop" msgid "Stop"
msgstr "Stopp" msgstr "Stopp"
#, fuzzy
msgid "Read" msgid "Read"
msgstr "Gelesen" msgstr "Gelesen"
@ -103,18 +115,22 @@ msgstr "Kann den Status der Folge nicht ändern"
msgid "Could not fetch episodes" msgid "Could not fetch episodes"
msgstr "Folgen können nicht abgerufen werden" msgstr "Folgen können nicht abgerufen werden"
#, fuzzy
msgid "Rewind 10 seconds" msgid "Rewind 10 seconds"
msgstr "10 Sekunden zurückspulen" msgstr "10 Sekunden zurückspulen"
msgid "Pause" msgid "Pause"
msgstr "Pause" msgstr "Pause"
#, fuzzy
msgid "Fast forward 30 seconds" msgid "Fast forward 30 seconds"
msgstr "30 Sekunden vorspulen" msgstr "30 Sekunden vorspulen"
#, fuzzy
msgid "Mute" msgid "Mute"
msgstr "Stumm" msgstr "Stumm"
#, fuzzy
msgid "Unmute" msgid "Unmute"
msgstr "Stummschalten" msgstr "Stummschalten"
@ -145,25 +161,31 @@ msgstr "Importiere OPML-Datei"
msgid "Rate RePod ❤️" msgid "Rate RePod ❤️"
msgstr "Bewerte RePod ❤️" msgstr "Bewerte RePod ❤️"
#, fuzzy
msgid "Sleep timer" msgid "Sleep timer"
msgstr "Einschlaftimer" msgstr "Einschlaftimer"
#, fuzzy
msgid "Minutes" msgid "Minutes"
msgstr "Minuten" msgstr "Minuten"
#, fuzzy
msgid "%n min" msgid "%n min"
msgid_plural "%n mins" msgid_plural "%n mins"
msgstr[0] "%n min" msgstr[0] "%n min"
msgstr[1] "%n mins" msgstr[1] "%n mins"
#, fuzzy
msgid "%n sec" msgid "%n sec"
msgid_plural "%n secs" msgid_plural "%n secs"
msgstr[0] "%s sec" msgstr[0] "%s sec"
msgstr[1] "%n secs" msgstr[1] "%n secs"
#, fuzzy
msgid "Playback speed" msgid "Playback speed"
msgstr "Wiedergabegeschwindigkeit" msgstr "Wiedergabegeschwindigkeit"
#, fuzzy
msgid "Favorite" msgid "Favorite"
msgstr "Favorit" msgstr "Favorit"
@ -173,6 +195,7 @@ msgstr "Bist Du sicher, dass Du das Abonnement löschen möchtest?"
msgid "Error while removing the feed" msgid "Error while removing the feed"
msgstr "Fehler beim Löschen des Feeds" msgstr "Fehler beim Löschen des Feeds"
#, fuzzy
msgid "You can only have 10 favorites" msgid "You can only have 10 favorites"
msgstr "Du kannst nur 10 Favoriten haben" msgstr "Du kannst nur 10 Favoriten haben"
@ -194,11 +217,14 @@ msgstr "Benötigte App fehlt"
msgid "Install GPodder Sync" msgid "Install GPodder Sync"
msgstr "Installiere GPodder Sync" msgstr "Installiere GPodder Sync"
#, fuzzy
msgid "Pin some subscriptions to see their latest updates" msgid "Pin some subscriptions to see their latest updates"
msgstr "Pinne einige Abonnements, um ihre neuesten Updates zu sehen" msgstr "Pinne einige Abonnements, um ihre neuesten Updates zu sehen"
#, fuzzy
msgid "No favorites" msgid "No favorites"
msgstr "Keine Favoriten" msgstr "Keine Favoriten"
#, fuzzy
msgid "A browser extension conflict with RePod" msgid "A browser extension conflict with RePod"
msgstr "Ein Browser-Erweiterungskonflikt mit RePod" msgstr "Ein Browser-Erweiterungskonflikt mit RePod"

View File

@ -62,6 +62,9 @@ msgstr ""
msgid "Download" msgid "Download"
msgstr "Télécharger" msgstr "Télécharger"
msgid "Skip to {match}"
msgstr "Sauter à {match}"
msgid "Add a RSS link" msgid "Add a RSS link"
msgstr "Ajouter un lien RSS" msgstr "Ajouter un lien RSS"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Nextcloud 3.14159\n" "Project-Id-Version: Nextcloud 3.14159\n"
"Report-Msgid-Bugs-To: translations\\@example.com\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" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -55,211 +55,215 @@ msgid ""
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:1 #: /app/specialVueFakeDummyForL10nScript.js:1
#: /app/specialVueFakeDummyForL10nScript.js:24
#: /app/specialVueFakeDummyForL10nScript.js:25 #: /app/specialVueFakeDummyForL10nScript.js:25
#: /app/specialVueFakeDummyForL10nScript.js:26
msgid "Download" msgid "Download"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:2 #: /app/specialVueFakeDummyForL10nScript.js:2
msgid "Add a RSS link" msgid "Skip to {match}"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:3 #: /app/specialVueFakeDummyForL10nScript.js:3
msgid "Add a RSS link"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:4 #: /app/specialVueFakeDummyForL10nScript.js:4
#: /app/specialVueFakeDummyForL10nScript.js:5 #: /app/specialVueFakeDummyForL10nScript.js:5
#: /app/specialVueFakeDummyForL10nScript.js:12 #: /app/specialVueFakeDummyForL10nScript.js:6
#: /app/specialVueFakeDummyForL10nScript.js:13
msgid "Subscribe" msgid "Subscribe"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:6 #: /app/specialVueFakeDummyForL10nScript.js:7
#: /app/specialVueFakeDummyForL10nScript.js:13 #: /app/specialVueFakeDummyForL10nScript.js:14
msgid "Error while adding the feed" msgid "Error while adding the feed"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:7 #: /app/specialVueFakeDummyForL10nScript.js:8
msgid "Could not fetch search results" msgid "Could not fetch search results"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:8 #: /app/specialVueFakeDummyForL10nScript.js:9
msgid "New podcasts" msgid "New podcasts"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:9 #: /app/specialVueFakeDummyForL10nScript.js:10
msgid "Hot podcasts" msgid "Hot podcasts"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:10 #: /app/specialVueFakeDummyForL10nScript.js:11
msgid "Could not fetch tops" msgid "Could not fetch tops"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:11 #: /app/specialVueFakeDummyForL10nScript.js:12
msgid "Copy feed" msgid "Copy feed"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:14 #: /app/specialVueFakeDummyForL10nScript.js:15
msgid "Link copied to the clipboard" msgid "Link copied to the clipboard"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:15
#: /app/specialVueFakeDummyForL10nScript.js:16 #: /app/specialVueFakeDummyForL10nScript.js:16
#: /app/specialVueFakeDummyForL10nScript.js:31 #: /app/specialVueFakeDummyForL10nScript.js:17
#: /app/specialVueFakeDummyForL10nScript.js:32
msgid "Play" msgid "Play"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:17
#: /app/specialVueFakeDummyForL10nScript.js:18 #: /app/specialVueFakeDummyForL10nScript.js:18
#: /app/specialVueFakeDummyForL10nScript.js:19
msgid "Stop" msgid "Stop"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:19
#: /app/specialVueFakeDummyForL10nScript.js:20 #: /app/specialVueFakeDummyForL10nScript.js:20
#: /app/specialVueFakeDummyForL10nScript.js:21 #: /app/specialVueFakeDummyForL10nScript.js:21
#: /app/specialVueFakeDummyForL10nScript.js:22
msgid "Read" msgid "Read"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:22
#: /app/specialVueFakeDummyForL10nScript.js:23 #: /app/specialVueFakeDummyForL10nScript.js:23
#: /app/specialVueFakeDummyForL10nScript.js:24
msgid "Open website" msgid "Open website"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:26 #: /app/specialVueFakeDummyForL10nScript.js:27
msgid "Could not change the status of the episode" msgid "Could not change the status of the episode"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:27
#: /app/specialVueFakeDummyForL10nScript.js:28 #: /app/specialVueFakeDummyForL10nScript.js:28
#: /app/specialVueFakeDummyForL10nScript.js:29
msgid "Could not fetch episodes" msgid "Could not fetch episodes"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:29 #: /app/specialVueFakeDummyForL10nScript.js:30
msgid "Rewind 10 seconds" msgid "Rewind 10 seconds"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:30 #: /app/specialVueFakeDummyForL10nScript.js:31
msgid "Pause" msgid "Pause"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:32 #: /app/specialVueFakeDummyForL10nScript.js:33
msgid "Fast forward 30 seconds" msgid "Fast forward 30 seconds"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:33
#: /app/specialVueFakeDummyForL10nScript.js:34 #: /app/specialVueFakeDummyForL10nScript.js:34
#: /app/specialVueFakeDummyForL10nScript.js:35 #: /app/specialVueFakeDummyForL10nScript.js:35
#: /app/specialVueFakeDummyForL10nScript.js:36
msgid "Mute" msgid "Mute"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:36 #: /app/specialVueFakeDummyForL10nScript.js:37
msgid "Unmute" msgid "Unmute"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:37 #: /app/specialVueFakeDummyForL10nScript.js:38
msgid "Export subscriptions" msgid "Export subscriptions"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:38 #: /app/specialVueFakeDummyForL10nScript.js:39
msgid "Filtering episodes" msgid "Filtering episodes"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:39 #: /app/specialVueFakeDummyForL10nScript.js:40
msgid "Show all" msgid "Show all"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:40 #: /app/specialVueFakeDummyForL10nScript.js:41
msgid "Listened" msgid "Listened"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:41 #: /app/specialVueFakeDummyForL10nScript.js:42
msgid "Listening" msgid "Listening"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:42 #: /app/specialVueFakeDummyForL10nScript.js:43
msgid "Unlistened" msgid "Unlistened"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:43 #: /app/specialVueFakeDummyForL10nScript.js:44
msgid "Import subscriptions" msgid "Import subscriptions"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:44 #: /app/specialVueFakeDummyForL10nScript.js:45
msgid "Import OPML file" msgid "Import OPML file"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:45 #: /app/specialVueFakeDummyForL10nScript.js:46
msgid "Rate RePod ❤️" msgid "Rate RePod ❤️"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:46 #: /app/specialVueFakeDummyForL10nScript.js:47
msgid "Sleep timer" msgid "Sleep timer"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:47 #: /app/specialVueFakeDummyForL10nScript.js:48
msgid "Minutes" msgid "Minutes"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:48 #: /app/specialVueFakeDummyForL10nScript.js:49
msgid "%n min" msgid "%n min"
msgid_plural "%n mins" msgid_plural "%n mins"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: /app/specialVueFakeDummyForL10nScript.js:49 #: /app/specialVueFakeDummyForL10nScript.js:50
msgid "%n sec" msgid "%n sec"
msgid_plural "%n secs" msgid_plural "%n secs"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: /app/specialVueFakeDummyForL10nScript.js:50 #: /app/specialVueFakeDummyForL10nScript.js:51
msgid "Playback speed" msgid "Playback speed"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:51
#: /app/specialVueFakeDummyForL10nScript.js:52 #: /app/specialVueFakeDummyForL10nScript.js:52
#: /app/specialVueFakeDummyForL10nScript.js:53 #: /app/specialVueFakeDummyForL10nScript.js:53
#: /app/specialVueFakeDummyForL10nScript.js:54
msgid "Favorite" msgid "Favorite"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:54 #: /app/specialVueFakeDummyForL10nScript.js:55
msgid "Are you sure you want to delete this subscription?" msgid "Are you sure you want to delete this subscription?"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:55 #: /app/specialVueFakeDummyForL10nScript.js:56
msgid "Error while removing the feed" msgid "Error while removing the feed"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:56 #: /app/specialVueFakeDummyForL10nScript.js:57
msgid "You can only have 10 favorites" msgid "You can only have 10 favorites"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:57 #: /app/specialVueFakeDummyForL10nScript.js:58
msgid "Add a podcast" msgid "Add a podcast"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:58 #: /app/specialVueFakeDummyForL10nScript.js:59
msgid "Could not fetch subscriptions" msgid "Could not fetch subscriptions"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:59 #: /app/specialVueFakeDummyForL10nScript.js:60
msgid "Find a podcast" msgid "Find a podcast"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:60 #: /app/specialVueFakeDummyForL10nScript.js:61
msgid "Error loading feed" msgid "Error loading feed"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:61 #: /app/specialVueFakeDummyForL10nScript.js:62
msgid "Missing required app" msgid "Missing required app"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:62 #: /app/specialVueFakeDummyForL10nScript.js:63
msgid "Install GPodder Sync" msgid "Install GPodder Sync"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:63 #: /app/specialVueFakeDummyForL10nScript.js:64
msgid "Pin some subscriptions to see their latest updates" msgid "Pin some subscriptions to see their latest updates"
msgstr "" msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:64 #: /app/specialVueFakeDummyForL10nScript.js:65
msgid "No favorites" msgid "No favorites"
msgstr "" msgstr ""

View File

@ -1,15 +1,15 @@
{ {
"extends": "@vue/tsconfig", "extends": "@vue/tsconfig",
"include": ["./src/**/*.ts", "./src/**/*.vue", "**/*.ts"], "include": ["./src/**/*.ts", "./src/**/*.vue", "**/*.ts"],
"compilerOptions": { "compilerOptions": {
"allowImportingTsExtensions": true, "allowImportingTsExtensions": true,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"target": "ESNext", "target": "ESNext",
"module": "ESNext", "module": "ESNext",
"moduleResolution": "Bundler", "moduleResolution": "Bundler",
"noImplicitAny": false, "noImplicitAny": false,
"rootDir": ".", "rootDir": ".",
"strict": true, "strict": true,
"noEmit": true, "noEmit": true
} }
} }