24 Commits

Author SHA1 Message Date
Jagandeep Brar
5a04fd95ed release: v10.2.4
[skip ci]
2023-04-09 14:20:11 -04:00
Jagandeep Brar
e3a21d2817 chore: update changelog_stable.json
[skip ci]
2023-04-09 14:19:36 -04:00
Jagandeep Brar
50714fa603 release(testflight): beta
[skip ci]
2023-04-07 02:32:27 -04:00
Jagandeep Brar
fe3d41af57 refactor(flavors): remove candidate flavor and merge with beta 2023-04-07 01:46:04 -04:00
Jagandeep Brar
1304ae327d release(testflight): candidate
[skip ci]
2023-04-05 23:09:52 -04:00
Jagandeep Brar
aeb80fcf08 release(testflight): beta
[skip ci]
2023-04-05 12:28:53 -04:00
Jagandeep Brar
a44ec79b3d chore(ci): fallback to commit hash for build run-name 2023-04-05 11:30:08 -04:00
Jagandeep Brar
a15d09b455 chore(locale): regenerate localization assets 2023-04-05 11:26:50 -04:00
Weblate (bot)
3aa2cc974c chore(locale): translations update from Weblate (#751)
Co-authored-by: Oğuz Ersen <oguz@ersen.moe>
Co-authored-by: Notis pap <notispap@hotmail.com>

[skip ci]
2023-04-05 11:25:06 -04:00
Jagandeep Brar
605002f5bd refactor: remove cupertino_icons and email_validator packages 2023-03-30 11:43:23 -04:00
Jagandeep Brar
2f94c42da1 refactor: remove riverpod state management 2023-03-30 11:43:23 -04:00
Jagandeep Brar
b65af75075 chore(locale): enable Greek (el) language 2023-03-30 04:12:40 -04:00
Weblate (bot)
4b149b58d0 chore(locale): translations update from Weblate
Co-authored-by: Notis pap <notispap@hotmail.com>
2023-03-30 04:10:41 -04:00
Jagandeep Brar
5ce12795e7 feat(settings): replace all strings with localizable strings 2023-03-30 04:07:10 -04:00
Jagandeep Brar
0f4ac9a893 feat(settings): add direct link to documentation for service notifications 2023-03-30 04:07:10 -04:00
Jagandeep Brar
4e243d6f30 release(testflight): beta
[skip ci]
2023-03-28 00:06:06 -04:00
Jagandeep Brar
568c28cd92 chore(ci): add run-name to build workflow
[skip ci]
2023-03-28 00:05:26 -04:00
Jagandeep Brar
3500d83477 fix(routing): handle pushing route which may return data 2023-03-27 17:41:23 -04:00
Jagandeep Brar
b515a0d14e chore(flutter): update packages 2023-03-27 16:42:31 -04:00
Jagandeep Brar
6a2e7d83f3 chore(locale): enable Slovak (sk) language 2023-03-27 16:39:07 -04:00
Jagandeep Brar
f1a82c06aa fix(images): utilize new technique to persistently cache images 2023-03-27 16:38:41 -04:00
Weblate (bot)
c5eace4352 chore(localization): translations update from Weblate
[skip ci]
2023-03-27 15:17:28 -04:00
Jagandeep Brar
781727abba fix(uiux): remove fading edge on horizontal scrollviews 2023-03-27 04:40:34 -04:00
Jagandeep Brar
7c8e17e59f chore: bump version to v10.2.4
[skip ci]
2023-03-27 04:36:15 -04:00
136 changed files with 1541 additions and 1264 deletions

View File

@@ -1,4 +1,5 @@
name: Build
run-name: "Build Release: ${{ inputs.flavor || github.sha }}"
on:
push:
@@ -14,7 +15,6 @@ on:
options:
- edge
- beta
- candidate
- stable
jobs:
@@ -29,7 +29,7 @@ jobs:
build-android:
name: Build Android
needs: [ prepare ]
needs: [prepare]
uses: JagandeepBrar/LunaSea/.github/workflows/build_android.yml@master
with:
build-number: ${{ needs.prepare.outputs.build-number }}
@@ -40,7 +40,7 @@ jobs:
build-ios:
name: Build iOS
needs: [ prepare ]
needs: [prepare]
uses: JagandeepBrar/LunaSea/.github/workflows/build_ios.yml@master
with:
build-number: ${{ needs.prepare.outputs.build-number }}
@@ -57,7 +57,7 @@ jobs:
build-linux:
name: Build Linux
needs: [ prepare ]
needs: [prepare]
uses: JagandeepBrar/LunaSea/.github/workflows/build_linux.yml@master
with:
build-number: ${{ needs.prepare.outputs.build-number }}
@@ -65,7 +65,7 @@ jobs:
build-macos:
name: Build macOS
needs: [ prepare ]
needs: [prepare]
uses: JagandeepBrar/LunaSea/.github/workflows/build_macos.yml@master
with:
build-number: ${{ needs.prepare.outputs.build-number }}
@@ -87,7 +87,7 @@ jobs:
build-web:
name: Build Web
needs: [ prepare ]
needs: [prepare]
uses: JagandeepBrar/LunaSea/.github/workflows/build_web.yml@master
with:
build-flavor: ${{ needs.prepare.outputs.build-flavor }}
@@ -98,7 +98,7 @@ jobs:
build-windows:
name: Build Windows
needs: [ prepare ]
needs: [prepare]
uses: JagandeepBrar/LunaSea/.github/workflows/build_windows.yml@master
secrets:
CODE_SIGNING_CERTIFICATE: ${{ secrets.CODE_SIGNING_CERTIFICATE }}
@@ -108,7 +108,7 @@ jobs:
publish-android:
name: Publish Android
needs: [ prepare, build-android ]
needs: [prepare, build-android]
uses: JagandeepBrar/LunaSea/.github/workflows/publish_android.yml@master
with:
build-flavor: ${{ needs.prepare.outputs.build-flavor }}
@@ -119,7 +119,7 @@ jobs:
publish-ios:
name: Publish iOS
needs: [ prepare, build-ios ]
needs: [prepare, build-ios]
uses: JagandeepBrar/LunaSea/.github/workflows/publish_ios.yml@master
with:
build-flavor: ${{ needs.prepare.outputs.build-flavor }}
@@ -134,7 +134,7 @@ jobs:
publish-linux:
name: Publish Linux
needs: [ prepare, build-linux ]
needs: [prepare, build-linux]
uses: JagandeepBrar/LunaSea/.github/workflows/publish_linux.yml@master
with:
build-flavor: ${{ needs.prepare.outputs.build-flavor }}
@@ -143,7 +143,7 @@ jobs:
publish-macos:
name: Publish macOS
needs: [ prepare, build-macos ]
needs: [prepare, build-macos]
uses: JagandeepBrar/LunaSea/.github/workflows/publish_macos.yml@master
with:
build-flavor: ${{ needs.prepare.outputs.build-flavor }}
@@ -158,7 +158,7 @@ jobs:
publish-web:
name: Publish Web
needs: [ prepare, build-web ]
needs: [prepare, build-web]
uses: JagandeepBrar/LunaSea/.github/workflows/publish_web.yml@master
with:
build-flavor: ${{ needs.prepare.outputs.build-flavor }}
@@ -168,7 +168,16 @@ jobs:
publish-s3:
name: Publish S3
needs: [ prepare, build-android, build-ios, build-linux, build-macos, build-web, build-windows ]
needs:
[
prepare,
build-android,
build-ios,
build-linux,
build-macos,
build-web,
build-windows,
]
uses: JagandeepBrar/LunaSea/.github/workflows/publish_s3.yml@master
with:
build-flavor: ${{ needs.prepare.outputs.build-flavor }}
@@ -183,7 +192,7 @@ jobs:
notify:
name: Notify
needs: [ prepare, publish-s3 ]
needs: [prepare, publish-s3]
uses: JagandeepBrar/LunaSea/.github/workflows/notify.yml@master
with:
build-flavor: ${{ needs.prepare.outputs.build-flavor }}
@@ -191,5 +200,4 @@ jobs:
secrets:
DISCORD_WEBHOOK_EDGE: ${{ secrets.DISCORD_WEBHOOK_EDGE }}
DISCORD_WEBHOOK_BETA: ${{ secrets.DISCORD_WEBHOOK_BETA }}
DISCORD_WEBHOOK_CANDIDATE: ${{ secrets.DISCORD_WEBHOOK_CANDIDATE }}
DISCORD_WEBHOOK_STABLE: ${{ secrets.DISCORD_WEBHOOK_STABLE }}

View File

@@ -1,4 +1,4 @@
name: 'Build Android'
name: "Build Android"
on:
workflow_call:
@@ -26,7 +26,7 @@ jobs:
firebase-token: ${{ secrets.FIREBASE_TOKEN }}
platform: android
android-key-jks: ${{ secrets.KEY_JKS }}
android-key-properties: ${{ secrets.KEY_PROPERTIES }}
android-key-properties: ${{ secrets.KEY_PROPERTIES }}
- name: Build LunaSea
working-directory: ${{ github.workspace }}/android
@@ -48,7 +48,7 @@ jobs:
firebase-token: ${{ secrets.FIREBASE_TOKEN }}
platform: android
android-key-jks: ${{ secrets.KEY_JKS }}
android-key-properties: ${{ secrets.KEY_PROPERTIES }}
android-key-properties: ${{ secrets.KEY_PROPERTIES }}
- name: Build LunaSea
working-directory: ${{ github.workspace }}/android

View File

@@ -1,4 +1,4 @@
name: 'Build iOS'
name: "Build iOS"
on:
workflow_call:
@@ -37,7 +37,7 @@ jobs:
with:
firebase-token: ${{ secrets.FIREBASE_TOKEN }}
platform: ios
match-ssh-private-key: ${{ secrets.MATCH_SSH_PRIVATE_KEY }}
match-ssh-private-key: ${{ secrets.MATCH_SSH_PRIVATE_KEY }}
- name: Build LunaSea
working-directory: ${{ github.workspace }}/ios
@@ -50,7 +50,7 @@ jobs:
MATCH_KEYCHAIN_NAME: ${{ secrets.MATCH_KEYCHAIN_NAME }}
MATCH_KEYCHAIN_PASSWORD: ${{ secrets.MATCH_KEYCHAIN_PASSWORD }}
run: bundle exec fastlane build_appstore build_number:${{ inputs.build-number }}
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:

View File

@@ -1,4 +1,4 @@
name: 'Build Linux'
name: "Build Linux"
on:
workflow_call:
@@ -25,7 +25,7 @@ jobs:
- name: Prepare Artifact
run: dart ${{github.workspace }}/scripts/generate_debian.dart "${{ inputs.build-version }}+${{ inputs.build-number }}"
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
@@ -46,7 +46,7 @@ jobs:
- name: Prepare Artifact
run: tar czf output/lunasea-linux-amd64.tar.gz -C build/linux/x64/release/bundle/ .
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
@@ -61,11 +61,11 @@ jobs:
uses: JagandeepBrar/LunaSea/.github/actions/prepare_for_build@master
with:
platform: linux
- name: Build LunaSea
uses: snapcore/action-build@v1
id: build
- name: Prepare Artifact
run: mv ${{ steps.build.outputs.snap }} ${{ github.workspace }}/output/lunasea-linux-amd64.snap
@@ -74,5 +74,3 @@ jobs:
with:
name: linux-snapcraft
path: ${{ github.workspace }}/output

View File

@@ -1,4 +1,4 @@
name: 'Build macOS'
name: "Build macOS"
on:
workflow_call:
@@ -49,7 +49,7 @@ jobs:
firebase-token: ${{ secrets.FIREBASE_TOKEN }}
platform: macos
appstore-connect-key: ${{ secrets.APPLE_STORE_CONNECT_KEY }}
match-ssh-private-key: ${{ secrets.MATCH_SSH_PRIVATE_KEY }}
match-ssh-private-key: ${{ secrets.MATCH_SSH_PRIVATE_KEY }}
- name: Build LunaSea
working-directory: ${{ github.workspace }}/macos
@@ -82,7 +82,7 @@ jobs:
firebase-token: ${{ secrets.FIREBASE_TOKEN }}
platform: macos
appstore-connect-key: ${{ secrets.APPLE_STORE_CONNECT_KEY }}
match-ssh-private-key: ${{ secrets.MATCH_SSH_PRIVATE_KEY }}
match-ssh-private-key: ${{ secrets.MATCH_SSH_PRIVATE_KEY }}
- name: Build LunaSea
working-directory: ${{ github.workspace }}/macos

View File

@@ -1,4 +1,4 @@
name: 'Build Web'
name: "Build Web"
on:
workflow_call:

View File

@@ -1,4 +1,4 @@
name: 'Build Windows'
name: "Build Windows"
on:
workflow_call:
@@ -27,7 +27,7 @@ jobs:
- name: Prepare Artifact
run: Compress-Archive -path ${{ github.workspace }}\build\windows\runner\Release\* ${{github.workspace}}\output\lunasea-windows-amd64.zip
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:

View File

@@ -1,4 +1,4 @@
name: 'GitHub Issue Labels'
name: "GitHub Issue Labels"
on:
issues:
@@ -12,7 +12,7 @@ jobs:
uses: dessant/support-requests@v2
with:
github-token: ${{ github.token }}
support-label: 'feature request'
support-label: "feature request"
issue-comment: >
Hi @{issue-author}! We use the issue tracker exclusively
for bug reports and issues. However, this issue appears
@@ -20,13 +20,13 @@ jobs:
to request new features.
close-issue: true
lock-issue: true
issue-lock-reason: 'off-topic'
issue-lock-reason: "off-topic"
- name: Support
uses: dessant/support-requests@v2
with:
github-token: ${{ github.token }}
support-label: 'support'
support-label: "support"
issue-comment: >
Hi @{issue-author}! We use the issue tracker exclusively
for bug reports and issues. However, this issue appears
@@ -39,4 +39,4 @@ jobs:
- [Subreddit](https://www.lunasea.app/reddit)
close-issue: true
lock-issue: true
issue-lock-reason: 'off-topic'
issue-lock-reason: "off-topic"

View File

@@ -15,8 +15,6 @@ on:
required: true
DISCORD_WEBHOOK_BETA:
required: true
DISCORD_WEBHOOK_CANDIDATE:
required: true
DISCORD_WEBHOOK_STABLE:
required: true
@@ -36,7 +34,6 @@ jobs:
env:
DISCORD_WEBHOOK_EDGE: ${{ secrets.DISCORD_WEBHOOK_EDGE }}
DISCORD_WEBHOOK_BETA: ${{ secrets.DISCORD_WEBHOOK_BETA }}
DISCORD_WEBHOOK_CANDIDATE: ${{ secrets.DISCORD_WEBHOOK_CANDIDATE }}
DISCORD_WEBHOOK_STABLE: ${{ secrets.DISCORD_WEBHOOK_STABLE }}
BUILD_FLAVOR: ${{ inputs.build-flavor }}
with:
@@ -44,7 +41,6 @@ jobs:
script: |
switch (process.env.BUILD_FLAVOR) {
case 'beta': return process.env.DISCORD_WEBHOOK_BETA;
case 'candidate': return process.env.DISCORD_WEBHOOK_CANDIDATE;
case 'stable': return process.env.DISCORD_WEBHOOK_STABLE;
case 'edge':
default: return process.env.DISCORD_WEBHOOK_EDGE;

View File

@@ -51,7 +51,7 @@ jobs:
run: |
COUNT=`git rev-list HEAD --count`
echo "commit-count=$COUNT" >> $GITHUB_OUTPUT
- name: Build Flavor
id: build-flavor
uses: actions/github-script@v6
@@ -64,7 +64,6 @@ jobs:
if (flavor) switch (flavor) {
case 'edge':
case 'beta':
case 'candidate':
case 'stable':
return flavor;
}
@@ -135,7 +134,7 @@ jobs:
export BUILD=${{ needs.build-details.outputs.build-number }}
export SENTRY_DSN=${{ secrets.SENTRY_DSN }}
flutter packages pub run environment_config:generate
- name: Generate Localization
run: dart ${{github.workspace }}/scripts/generate_localization.dart

View File

@@ -44,11 +44,10 @@ jobs:
script: |
const ref = process.env.FLAVOR || 'edge';
switch (ref) {
case 'beta': return 'alpha';
case 'candidate': return 'beta';
case 'beta': return 'beta';
case 'stable': return 'production';
case 'edge':
default: return 'internal';
default: return 'alpha';
}
- name: Generate Changelog
@@ -58,7 +57,7 @@ jobs:
run: |
mkdir -p $OUTPUT_PATH
echo $MOTD > $OUTPUT_PATH/default.txt
- name: Deploy to Google Play Store
working-directory: ${{ github.workspace }}/android
env:

View File

@@ -109,7 +109,7 @@ jobs:
- name: Upload to S3 Bucket (Build Title)
uses: jakejarvis/s3-sync-action@v0.5.1
with:
args: --acl public-read --follow-symlinks
args: --acl public-read --follow-symlinks
env:
AWS_ACCESS_KEY_ID: ${{ secrets.S3_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_ACCESS_KEY }}
@@ -122,7 +122,7 @@ jobs:
- name: Upload to S3 Bucket (Latest)
uses: jakejarvis/s3-sync-action@v0.5.1
with:
args: --acl public-read --follow-symlinks
args: --acl public-read --follow-symlinks
env:
AWS_ACCESS_KEY_ID: ${{ secrets.S3_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_ACCESS_KEY }}

View File

@@ -64,7 +64,6 @@ jobs:
const ref = process.env.FLAVOR || 'edge';
switch (ref) {
case 'beta': return '11ef2676-fc31-41b5-897b-fd21273d87ed';
case 'candidate': return '4636e6a1-17ef-45a2-a2b6-3d1c166fd1df';
case 'stable': return '6634f0b1-323c-4a2f-bd0b-8f1f388673a9';
case 'edge':
default: return '325e197e-55f4-449a-b2bb-6831fe47bf2a';

View File

@@ -2,6 +2,28 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [10.2.4](https://github.com/JagandeepBrar/LunaSea/compare/v10.2.3...v10.2.4) (2023-04-09)
### Features
* **settings:** add direct link to documentation for service notifications ([0f4ac9a](https://github.com/JagandeepBrar/LunaSea/commit/0f4ac9a893d5b13a732db49e0bfc7b09fe7c05d9))
* **settings:** replace all strings with localizable strings ([5ce1279](https://github.com/JagandeepBrar/LunaSea/commit/5ce12795e7223a543bd037151b1a3eaa484f2634))
### Bug Fixes
* **images:** utilize new technique to persistently cache images ([f1a82c0](https://github.com/JagandeepBrar/LunaSea/commit/f1a82c06aa58fe493af2b2b0bf9ef8a93011802b))
* **routing:** handle pushing route which may return data ([3500d83](https://github.com/JagandeepBrar/LunaSea/commit/3500d83477880b8ee490132bc270e632af4a4bb1))
* **uiux:** remove fading edge on horizontal scrollviews ([781727a](https://github.com/JagandeepBrar/LunaSea/commit/781727abbab0dc70d959c723c3d101e66430ac60))
### Tweaks
* **flavors:** remove candidate flavor and merge with beta ([fe3d41a](https://github.com/JagandeepBrar/LunaSea/commit/fe3d41af57717b994e71370968404fc05f20f72b))
* remove cupertino_icons and email_validator packages ([605002f](https://github.com/JagandeepBrar/LunaSea/commit/605002f5bd4b015791d3d1f260e03b4127c5020d))
* remove riverpod state management ([2f94c42](https://github.com/JagandeepBrar/LunaSea/commit/2f94c42da1a97847be4a77e79d096eb0212a9657))
### [10.2.3](https://github.com/JagandeepBrar/LunaSea/compare/v10.2.2...v10.2.3) (2023-03-22)

View File

@@ -1,46 +1,47 @@
{
"motd": "Welcome to LunaSea v10.2.3!\n\nThis update adds the ability to open Tautulli library items directly in Plex and more details about activity streams.",
"motd": "Welcome to LunaSea v10.2.4!\n\nThis update fixes some small underlying issues with network image caching and text rendering. To further improve scrolling performance of large lists of content (especially on lower-end devices), the horizontal fading edge of scrollable text has been removed.\n\nFor testers of pre-release builds, beta and candidate release channels have now been combined for simplicity. For more information on early release channels, check out the page in the documentation (a direct link is available in the Resources section of the settings).",
"feat": {
"tautulli": [
"settings": [
{
"commit": "5cf1a06cec079aa66c77425c0ed8d4fa7897bbd3",
"message": "add ability to open media in Plex"
"commit": "0f4ac9a893d5b13a732db49e0bfc7b09fe7c05d9",
"message": "add direct link to documentation for service notifications"
},
{
"commit": "6de806316efaa61c5ddbac1b8f5b214949f0bcf8",
"message": "display audio language, subtitle language, and video dynamic range for activity"
}
],
"flutter": [
{
"commit": "6241ee462989f1f65fa8f1e18378579e2e77197b",
"message": "replace Skia with Impeller rendering engine"
},
{
"commit": "f1b831a118e56c480aae72042ee4eb7013f954b2",
"message": "upgrade to Flutter 3.7.7/1837b5be5f"
"commit": "5ce12795e7223a543bd037151b1a3eaa484f2634",
"message": "replace all strings with localizable strings"
}
]
},
"fix": {
"links": [
"images": [
{
"commit": "596eab4bad1aa183e3c0dfc8d20a32c15ecdb78d",
"message": "use platform default method to launch URLs"
"commit": "f1a82c06aa58fe493af2b2b0bf9ef8a93011802b",
"message": "more efficiently cache persistent network images"
}
],
"http": [
"uiux": [
{
"commit": "aca5d0eb826b38ebeec33e3495045bf21e8a49c7",
"message": "correctly set content type for POST requests"
}
],
"macos": [
{
"commit": "d612ae221cac741b3a36893d4bc7f05f5055c7b8",
"message": "set minimum platform version to 10.15"
"commit": "781727abbab0dc70d959c723c3d101e66430ac60",
"message": "remove fading edge on horizontal scroll-views"
}
]
},
"refactor": {}
"refactor": {
"flavors": [
{
"commit": "fe3d41af57717b994e71370968404fc05f20f72b",
"message": "remove candidate flavor and merge with beta"
}
],
"flutter": [
{
"commit": "605002f5bd4b015791d3d1f260e03b4127c5020d",
"message": "remove unused packages"
},
{
"commit": "4b149b58d0eaab53a39917152ff224f7b6e93c0f",
"message": "translations update from Weblate"
}
]
}
}

118
assets/localization/el.json Normal file
View File

@@ -0,0 +1,118 @@
{
"dashboard.Friday": "Παρασκευή",
"dashboard.FutureDays": "Μελλοντικό χρόνο",
"dashboard.OneMonth": "Ένας μήνας",
"dashboard.Tuesday": "Τρίτη",
"dashboard.MinimumOfOneDay": "1 ημέρα το ελάχιστο",
"dashboard.Modules": "Ενότητες",
"dashboard.Monday": "Δευτέρα",
"dashboard.NoNewContent": "Τίποτα νέο",
"dashboard.OneWeek": "Μία εβδομάδα",
"dashboard.PastDays": "Παλαιότερες ημέρες",
"dashboard.Saturday": "Σάββατο",
"dashboard.Schedule": "Πρόγραμμα",
"dashboard.Sunday": "Κυριακή",
"dashboard.Thursday": "Πέμπτη",
"dashboard.Calendar": "Ημερολόγιο",
"dashboard.PastDaysDescription": "Τοποθετήσει τον αριθμό ημερών στο παρελθόν για εισαγωγή των εγγραφών του ημερολογίου.",
"dashboard.TwoWeeks": "Δύο εβδομάδες",
"dashboard.Wednesday": "Τετάρτη",
"dashboard.FutureDaysDescription": "Τοποθετήσει τον αριθμό ημερών στο μέλλον για εισαγωγή των εγγραφών του ημερολογίου.",
"lidarr.StartSearchForMissingAlbums": "Ξεκίνα αναζήτηση για άλμπουμ που λείπουν",
"lidarr.StartSearchFor": "Ξεκίνα αναζήτηση…",
"lunasea.Add": "Προσέθεσε",
"lunasea.Alpha": "Πρώτη",
"lunasea.AnErrorHasOccurred": "Κάποιο σφάλμα δημιουργήθηκε",
"lunasea.Ascending": "Αύξουσα",
"lunasea.BackUp": "Αντίγραφα ασφαλείας",
"lunasea.Beta": "Δοκιμαστική",
"lunasea.BlockView": "Εμφάνιση σε blocks",
"lunasea.BuyMeABeer": "Κέρασε με μια μπύρα",
"lunasea.BuyMeABurger": "Κέρασε με ένα burger",
"lunasea.BuyMeACoffee": "Κέρασε με ένα καφέ",
"lunasea.BuyMeASoda": "Κέρασε με ένα αναψυκτικό",
"lunasea.Cancel": "Ακύρωση",
"lunasea.Candidate": "Υποψήφιος",
"lunasea.ChangeProfiles": "Αλλαγή προφίλ",
"lunasea.Changelog": "Αλλαγές",
"lunasea.CheckLogsMessage": "Δες τις καταγραφές για περισσότερες λεπτομέρειες",
"lunasea.Chores": "Μικρό δουλειές",
"lunasea.Clear": "Καθαρισμός",
"lunasea.Close": "Κοντά",
"lunasea.ComingSoon": "Έρχονται σύντομα",
"lunasea.Copied": "Αντιγράφτηκε",
"lunasea.Critical": "Κρίσιμο",
"lunasea.Dashboard": "Ταμπλό",
"lunasea.Days": "{} ημέρες",
"lunasea.DaysAgo": "{} παλαιότερες ημέρες",
"lunasea.Debug": "Εντοπισμός σφαλμάτων",
"lunasea.Delete": "Διαγράφω",
"lunasea.Descending": "Φθίνουσα",
"lunasea.Develop": "Ανάπτυξη",
"lunasea.Disable": "Απενεργοποιώ",
"lunasea.Disabled": "Ανενεργός",
"lunasea.Dismiss": "Απόρριψη",
"lunasea.Docs": "Έγγραφα",
"lunasea.DownloadClient": "Πρόγραμμα λήψης",
"lunasea.Edge": "Χείλος",
"lunasea.Error": "Σφάλμα",
"lunasea.ExternalModules": "Εξωτερικές μονάδες",
"lunasea.Features": "Χαρακτηριστικά",
"lunasea.Fixes": "Επιδιορθώσεις",
"lunasea.FullChangelog": "Πλήρες ημερολόγιο αλλαγών",
"lunasea.GoBack": "Επιστροφή",
"lunasea.GoToSettings": "Πήγαινε στις ρυθμίσεις",
"lunasea.GridView": "Προβολή πλέγματος",
"lunasea.Home": "Αρχική σελίδα",
"lunasea.Hours": "{} ώρες",
"lunasea.HoursAgo": "{} ώρες πριν",
"lunasea.IncorrectEncryptionKey": "Λανθασμένο κλειδί κρυπτογράφησης",
"lunasea.Internal": "Εσωτερικό",
"lunasea.InvalidFileTypeSelected": "Επιλέχθηκε μη έγκυρος τύπος αρχείου",
"lunasea.JustNow": "Αμέσως",
"lunasea.Minutes": "{} Λεπτά",
"lunasea.MinutesAgo": "{} λεπτά πριν",
"lunasea.Module": "Μονάδα",
"overseerr.Audio": "Ήχος",
"overseerr.Approved": "Έγκριση",
"overseerr.Available": "Διαθέσιμο",
"overseerr.Declined": "Απορρίφθηκε",
"overseerr.Issues": "Θέματα",
"overseerr.NoIssues": "Κανένα Θέμα",
"overseerr.NoIssuesFound": "Κανένα θέμα δεν βρέθηκε",
"overseerr.NoRequests": "Χωρίς αιτήματα",
"overseerr.NoRequestsFound": "Κανένα αίτημα δεν βρέθηκε",
"overseerr.OneRequest": "1 Αίτημα",
"overseerr.Open": "Ανοιχτό",
"radarr.AddMovie": "Προσθήκη ταινίας",
"radarr.AddMovieAndSearch": "Προσθήκη + αναζήτηση",
"radarr.AddedTag": "Προσθήκη ετικέτας",
"radarr.Age": "Ηλικία",
"radarr.All": "Όλα",
"sabnzbd.All": "Όλα",
"sabnzbd.Ascending": "Αύξουσα",
"sabnzbd.Age": "Ηλικία",
"sabnzbd.CategoryDefault": "Προεπιλογή κατηγορίας",
"search.AddIndexer": "Προσθήκη Indexer",
"search.Age": "Ηλικία",
"search.AllSubcategories": "Όλες οι υποκατηγορίες",
"search.Alphabetical": "Αλφαβητικά",
"search.Category": "Κατηγορία",
"settings.AccountDeleted": "Διαγραφή λογαριασμού",
"settings.AccountDescription": "Ο LunaSea λογαριασμός σου",
"settings.AccountDeletedMessage": "Διαγραφή λογαριασμού LunaSea",
"settings.Account": "Λογαριασμός",
"sonarr.AddedSeries": "Προστέθηκε σειρά",
"sonarr.AddedTag": "Προσθήκη ετικέτας",
"sonarr.AddReleaseToBlocklist": "Προσθήκη έκδοσης στην λίστα αποκλεισμού",
"sonarr.AddedOn": "Προστέθηκε στις",
"sonarr.AddSeries": "Προσθήκη σειρών",
"tautulli.Activity": "Δραστηριότητα",
"tautulli.ActivityDetails": "Λεπτομέρειες δραστηριότητας",
"tautulli.ActivityRefreshRate": "Ρυθμός ανανέωσης δραστηριότητας",
"tautulli.Audio": "Ήχος",
"tautulli.BackingUpConfiguration": "Δημιουργία αντιγράφων ασφαλείας διαμόρφωσης…",
"wake_on_lan.MagicPacketSent": "Αποστολή Magic Packet",
"wake_on_lan.MagicPacketSentMessage": "Το μηχάνημα πρέπει να εκκινεί!",
"wake_on_lan.MagicPacketFailedToSend": "Αποτυχία αποστολής Magic Packet"
}

View File

@@ -57,6 +57,8 @@
"lunasea.DownloadClient": "Download Client",
"lunasea.Edge": "Edge",
"lunasea.Error": "Error",
"lunasea.EverySecond": "Every Second",
"lunasea.EverySeconds": "Every {} Seconds",
"lunasea.ExternalModules": "External Modules",
"lunasea.Features": "Features",
"lunasea.Fixes": "Fixes",
@@ -70,6 +72,7 @@
"lunasea.IncorrectEncryptionKey": "Incorrect encryption key",
"lunasea.Internal": "Internal",
"lunasea.InvalidFileTypeSelected": "Invalid File Type Selected",
"lunasea.Items": "{} Items",
"lunasea.JustNow": "Just Now",
"lunasea.Minutes": "{} Minutes",
"lunasea.MinutesAgo": "{} Minutes Ago",
@@ -85,6 +88,7 @@
"lunasea.OneDayAgo": "1 Day Ago",
"lunasea.OneHour": "1 Hour",
"lunasea.OneHourAgo": "1 Hour Ago",
"lunasea.OneItem": "1 Item",
"lunasea.OneMinute": "1 Minute",
"lunasea.OneMinuteAgo": "1 Minute Ago",
"lunasea.OneMonth": "1 Month",
@@ -113,6 +117,8 @@
"lunasea.Settings": "Settings",
"lunasea.Stable": "Stable",
"lunasea.StartingView": "Starting View",
"lunasea.ThankYou": "Thank You",
"lunasea.ThankYouMessage": "Thank you for supporting the open-source community!",
"lunasea.Today": "Today",
"lunasea.TransactionFailure": "Transaction Failure",
"lunasea.TryAgain": "Try Again",
@@ -181,6 +187,8 @@
"radarr.DigitalRelease": "Digital Release",
"radarr.DirectoryNotFound": "Directory Not Found",
"radarr.Discover": "Discover",
"radarr.DiscoverSuggestions": "Discover Suggestions",
"radarr.DiscoverSuggestionsDescription": "Add Suggested Releases in Discover",
"radarr.Disks": "Disks",
"radarr.DownloadFailed": "Download Failed",
"radarr.DownloadIgnored": "Download Ignored",
@@ -215,6 +223,7 @@
"radarr.MoveFilesDescription": "Would you like to move the files?",
"radarr.MoveFull": "Move Files",
"radarr.Movie": "Movie",
"radarr.MovieDetails": "Movie Details",
"radarr.Movies": "Movies",
"radarr.MovieFileDeleted": "Movie File Deleted",
"radarr.MovieFileRenamed": "Movie File Renamed",
@@ -237,6 +246,7 @@
"radarr.QualityProfile": "Quality Profile",
"radarr.Queue": "Queue",
"radarr.QueueDescription": "View Active & Queued Content",
"radarr.QueueSize": "Queue Size",
"radarr.Quick": "Quick",
"radarr.RefreshMovie": "Refresh Movie",
"radarr.Rejected": "Rejected",
@@ -306,25 +316,39 @@
"sabnzbd.ShutdownSABnzbd": "Shutdown SABnzbd",
"sabnzbd.StandbyPC": "Standby PC",
"sabnzbd.Stop": "Stop",
"search.AddIndexer": "Add Indexer",
"search.Age": "Age",
"search.AllSubcategories": "All Subcategories",
"search.Alphabetical": "Alphabetical",
"search.Category": "Category",
"search.Categories": "Categories",
"search.Comments": "Comments",
"search.DeleteIndexer": "Delete Indexer",
"search.Download": "Download",
"search.Downloading": "Downloading…",
"search.DownloadingNZBToDevice": "Downloading NZB to your device",
"search.DownloadToDevice": "Download to Device",
"search.EditIndexer": "Edit Indexer",
"search.FailedToAddIndexer": "Failed to Add indexer",
"search.FailedToDownloadNZB": "Failed to Download NZB",
"search.FailedToSend": "Failed to Send",
"search.HideAdultCategories": "Hide Adult Categories",
"search.HideAdultCategoriesDescription": "Hide Adult Content",
"search.IndexerAPIHost": "Indexer API Host",
"search.IndexerAPIKey": "Indexer API Key",
"search.IndexerAdded": "Indexer Added",
"search.IndexerDeleted": "Indexer Deleted",
"search.IndexerNotFound": "Indexer Not Found",
"search.NoCategoriesFound": "No Categories Found",
"search.NoIndexersFound": "No Indexers Found",
"search.NoResultsFound": "No Results Found",
"search.NoSubcategoriesFound": "No Subcategories Found",
"search.Results": "Results",
"search.Search": "Search",
"search.SentNZBData": "Sent NZB Data",
"search.SentTo": "Sent to {}",
"search.ShowLinks": "Show Links",
"search.ShowLinksDescription": "Show Download and Comments Links",
"search.Size": "Size",
"search.Subcategories": "Subcategories",
"settings.Account": "Account",
@@ -343,6 +367,8 @@
"settings.AddProfileDescription": "Add a New Profile",
"settings.AddedProfile": "Added Profile",
"settings.AllFieldsAreRequired": "All fields are required",
"settings.AllLogs": "All Logs",
"settings.AllLogsDescription": "View Logs of All Types",
"settings.AmoledTheme": "AMOLED Theme",
"settings.AmoledThemeBorders": "AMOLED Theme Borders",
"settings.AmoledThemeBordersDescription": "Add Subtle Borders Across the UI",
@@ -381,25 +407,35 @@
"settings.BuildChannels": "Build Channels",
"settings.BuildChannelsDescription": "Learn About Additional Build Channels",
"settings.CalendarSettings": "Calendar Settings",
"settings.CalendarSettingsDescription": "Customize the Unified Calendar",
"settings.ChangedProfile": "Changed Profile",
"settings.Channel": "Channel",
"settings.Class": "Class",
"settings.CleanSlate": "Clean Slate",
"settings.Clear": "Clear",
"settings.ClearConfiguration": "Clear Configuration",
"settings.ClearConfigurationHint1": "Are you sure you want to clear your configuration?",
"settings.ClearConfigurationHint2": "You will be starting from a clean slate, please ensure you backup your current configuration first!",
"settings.ClearConfigurationHint3": "If you are signed into a LunaSea account, you will be signed out.",
"settings.ClearImageCache": "Clear Image Cache",
"settings.ClearImageCacheDescription": "Clear Images From Persistent Storage",
"settings.ClearImageCacheHint1": "Are you sure you want to clear all images from the cache?",
"settings.ClearImageCacheHint2": "Redownloading images for a large library can consume a large amount of data.",
"settings.ClearImageCacheHint2": "Re-downloading images for a large library can consume a large amount of data.",
"settings.ClearLogs": "Clear Logs",
"settings.ClearLogsHint1": "Are you sure you want to clear all recorded logs?\n\nLogs can be useful for bug reports and debugging.",
"settings.ConfigureModule": "Configure {}",
"settings.Configuration": "Configuration",
"settings.ConfigurationCleared": "Configuration Cleared",
"settings.ConfigurationClearedDescription": "Your configuration has been cleared",
"settings.ConfigurationDescription": "Configure & Setup LunaSea",
"settings.ConnectedSuccessfully": "Connected",
"settings.ConnectedSuccessfullyMessage": "{} is ready to use with LunaSea!",
"settings.ConnectionDetails": "Connection Details",
"settings.ConnectionDetailsDescription": "Connection Details for {}",
"settings.ConnectionTestFailed": "Connection Test Failed",
"settings.CopiedURLFor": "Copied URL for {}",
"settings.CopiedDeviceURL": "Copied your device-based URL to the clipboard",
"settings.CopiedUserURL": "Copied your user-based URL to the clipboard",
"settings.CurrentPassword": "Current Password",
"settings.Custom": "Custom…",
"settings.CustomHeader": "Custom Header",
@@ -440,6 +476,7 @@
"settings.DeleteModuleSuccess": "Module Deleted",
"settings.DeleteProfile": "Delete Profile",
"settings.DeleteProfileDescription": "Delete an Existing Profile",
"settings.Device": "Device",
"settings.DiscordDescription": "Request Features & Get Support",
"settings.DismissBanners": "Dismiss Banners",
"settings.DismissBannersHint1": "Are you sure you want to dismiss all tooltip banners?",
@@ -463,6 +500,12 @@
"settings.EnableModule": "Enable {}",
"settings.EnabledProfile": "Enabled Profile",
"settings.EncryptionKey": "Encryption Key",
"settings.Exception": "Exception",
"settings.Export": "Export",
"settings.ExportedLogs": "Exported Logs",
"settings.ExportedLogsMessage": "Logs have been successfully exported",
"settings.FailedToClearImageCache": "Failed to Clear Image Cache",
"settings.FailedToClearImageCacheDescription": "The image cache could not be cleared",
"settings.FailedToDeleteAccount": "Failed to Delete Account",
"settings.FailedToUpdateEmail": "Failed to Update Email",
"settings.FailedToUpdatePassword": "Failed to Update Password",
@@ -471,6 +514,8 @@
"settings.FutureDays": "Future Days",
"settings.General": "General",
"settings.GeneralDescription": "Customize LunaSea",
"settings.GettingStarted": "Getting Started",
"settings.GettingStartedDescription": "Information & Setup Instructions",
"settings.GitHubDescription": "View the Source Code",
"settings.HeaderAdded": "Header Added",
"settings.HeaderDeleted": "Header Deleted",
@@ -491,6 +536,8 @@
"settings.ImageBackgroundOpacity": "Image Background Opacity",
"settings.ImageBackgroundOpacityHint1": "Set the opacity of background images.",
"settings.ImageBackgroundOpacityHint2": "To completely disable fetching background images, set the value to 0.",
"settings.ImageCacheCleared": "Image Cache Cleared",
"settings.ImageCacheClearedDescription": "The image cache has been cleared",
"settings.InvalidEmail": "Invalid Email Address",
"settings.InvalidEmailMessage": "The email address is invalid",
"settings.InvalidPassword": "Invalid Password",
@@ -498,11 +545,16 @@
"settings.Language": "Language",
"settings.Localization": "Localization",
"settings.LocalizationDescription": "Customize to your Locale",
"settings.Logs": "Logs",
"settings.LogsCleared": "Logs Cleared",
"settings.LogsClearedDescription": "All recorded logs have been cleared",
"settings.LogsDescription": "View, Export, and Clear Logs",
"settings.Method": "Method",
"settings.MACAddress": "MAC Address",
"settings.MACAddressHint1": "This is the MAC address of the machine that you want to wake up",
"settings.MACAddressHint2": "MAC addresses contain six two-digit hexidecimal nibbles (an octet)",
"settings.MACAddressHint3": "Hexidecimal digits range from 0-9 and A-F",
"settings.MACAddressHint4": "Each hexidecimal octet should be separated by a colon",
"settings.MACAddressHint2": "MAC addresses contain six two-digit hexadecimal nibbles (an octet)",
"settings.MACAddressHint3": "Hexadecimal digits range from 0-9 and A-F",
"settings.MACAddressHint4": "Each hexadecimal octet should be separated by a colon",
"settings.MACAddressValidation": "Invalid MAC Address",
"settings.MinimumCharacters": "Minimum of {} characters",
"settings.ModuleNotFound": "Module Not Found",
@@ -510,12 +562,16 @@
"settings.Network": "Network",
"settings.NetworkDescription": "Customize Network Features",
"settings.NewPassword": "New Password",
"settings.NotAuthorized": "Not Authorized",
"settings.NotAuthorizedMessage": "LunaSea is not authorized to show notifications. Please go to your device's settings to enable notifications.",
"settings.NotAvailable": "Not Available",
"settings.Notifications": "Notifications",
"settings.NotificationsDescription": "Set up Webhooks for Push Notifications",
"settings.NoAdditionalProfilesAdded": "No additional profiles have been added",
"settings.NoBackupsFound": "No Backups Found",
"settings.NoExternalModulesFound": "No External Modules Found",
"settings.NoHeadersAdded": "No Headers Added",
"settings.NoLogsFound": "No Logs Found",
"settings.NoProfilesFound": "No Profiles Found",
"settings.OpenDrawerOnBackAction": "Open Drawer on Back Action",
"settings.OpenDrawerOnBackActionDescription": "Open the drawer instead of closing LunaSea",
@@ -586,6 +642,7 @@
"settings.UpToDate": "Up To Date",
"settings.Use24HourTime": "Use 24 Hour Time",
"settings.Use24HourTimeDescription": "Show Timestamps in 24 Hour Style",
"settings.User": "User",
"settings.Username": "Username",
"settings.UsernameValidation": "Username Required",
"settings.Version": "Version",
@@ -728,6 +785,7 @@
"sonarr.Queue": "Queue",
"sonarr.Queued": "Queued",
"sonarr.QueueDescription": "View Active & Queued Content",
"sonarr.QueueSize": "Queue Size",
"sonarr.Reason": "Reason",
"sonarr.RefreshSeries": "Refresh Series",
"sonarr.Rejected": "Rejected",
@@ -807,6 +865,7 @@
"sonarr.WordScore": "Word Score",
"tautulli.Activity": "Activity",
"tautulli.ActivityDetails": "Activity Details",
"tautulli.ActivityRefreshRate": "Activity Refresh Rate",
"tautulli.Audio": "Audio",
"tautulli.BackingUpConfiguration": "Backing Up Configuration…",
"tautulli.BackingUpConfigurationDescription": "Backing up your configuration in the background",
@@ -821,6 +880,7 @@
"tautulli.Converting": "Converting",
"tautulli.Container": "Container",
"tautulli.Copy": "Copy",
"tautulli.DefaultTerminationMessage": "Default Termination Message",
"tautulli.DeleteCache": "Delete Cache",
"tautulli.DeleteImageCache": "Delete Image Cache",
"tautulli.DeleteTemporarySessions": "Delete Temporary Sessions",
@@ -840,9 +900,12 @@
"tautulli.Duration": "Duration",
"tautulli.Episode": "Episode {}",
"tautulli.ETA": "ETA",
"tautulli.Graphs": "Graphs",
"tautulli.History": "History",
"tautulli.Library": "Library",
"tautulli.LibraryDetails": "Library Details",
"tautulli.Location": "Location",
"tautulli.MediaDetails": "Media Details",
"tautulli.Metadata": "Metadata",
"tautulli.More": "More",
"tautulli.None": "None",
@@ -857,6 +920,8 @@
"tautulli.SessionsOne": "1 Session",
"tautulli.SessionsMany": "{} Sessions",
"tautulli.Speed": "Speed: {}x",
"tautulli.Statistics": "Statistics",
"tautulli.StatisticsItemCount": "Statistics Item Count",
"tautulli.Stream": "Stream",
"tautulli.Subtitle": "Subtitle",
"tautulli.Terminate": "Terminate",
@@ -872,6 +937,7 @@
"tautulli.Transcodes": "Transcodes",
"tautulli.User": "User",
"tautulli.Users": "Users",
"tautulli.UserDetails": "User Details",
"tautulli.Video": "Video",
"tautulli.ViewWebGUI": "View Web GUI",
"tautulli.Year": "Year",

132
assets/localization/sk.json Normal file
View File

@@ -0,0 +1,132 @@
{
"dashboard.Calendar": "Kalendár",
"dashboard.Friday": "Piatok",
"dashboard.MinimumOfOneDay": "Minimálne 1 deň",
"dashboard.Modules": "Moduly",
"dashboard.Monday": "Pondelok",
"dashboard.OneMonth": "Jeden mesiac",
"dashboard.OneWeek": "Jeden týždeň",
"dashboard.PastDays": "Uplynulé dni",
"dashboard.PastDaysDescription": "Vyberte počet dní v minulosti, pre ktoré sa majú načítať záznamy z kalendára.",
"dashboard.Saturday": "Sobota",
"dashboard.Schedule": "Prehľad",
"dashboard.Sunday": "Nedeľa",
"dashboard.FutureDaysDescription": "Vyberte počet dní v budúcnosti, pre ktoré sa majú načítať záznamy z kalendára.",
"dashboard.TwoWeeks": "Dva týždne",
"dashboard.Wednesday": "Streda",
"dashboard.FutureDays": "Budúce dni",
"dashboard.Tuesday": "Utorok",
"dashboard.NoNewContent": "Žiadny nový obsah",
"dashboard.Thursday": "Štvrtok",
"lidarr.StartSearchFor": "Začnite hľadať…",
"lidarr.StartSearchForMissingAlbums": "Začnite hľadať chýbajúce albumy",
"overseerr.Approved": "Schválené",
"overseerr.Issues": "Problémy",
"overseerr.NoIssues": "Žiadne problémy",
"overseerr.NoIssuesFound": "Nenašli sa žiadne problémy",
"overseerr.NoRequests": "Žiadne požiadavky",
"overseerr.NoRequestsFound": "Nenašli sa žiadne požiadavky",
"overseerr.OneRequest": "1 požiadavka",
"overseerr.Open": "Otvorené",
"overseerr.Other": "Iné",
"overseerr.PartiallyAvailable": "Čiastočne dostupné",
"overseerr.Pending": "Čakajúce",
"overseerr.SomeRequests": "Požiadavky",
"overseerr.Resolved": "Vyriešené",
"overseerr.RequestedBy": "Vyžiadané {}",
"overseerr.Requests": "Požiadavky",
"overseerr.Subtitle": "Titulky",
"overseerr.Users": "Používatelia",
"overseerr.Video": "Video",
"overseerr.Requested": "Vyžiadané",
"overseerr.Declined": "Zamietnuté",
"overseerr.OpenedBy": "Otvorené",
"overseerr.Audio": "Audio",
"overseerr.Processing": "Spracovávané",
"overseerr.Available": "Dostupné",
"overseerr.NoUsersFound": "Žiadni nájdení používatelia",
"overseerr.UnknownUser": "Neznámy používateľ",
"sabnzbd.All": "Všetky",
"sabnzbd.Ascending": "Vzostupne",
"sabnzbd.CategoryDefault": "Predvolená kategória",
"sabnzbd.Completed": "Dokončené",
"sabnzbd.Descending": "Zostupne",
"sabnzbd.Duplicate": "Duplikát",
"sabnzbd.Force": "Vynútiť",
"sabnzbd.High": "Vysoká",
"sabnzbd.Name": "Názov",
"sabnzbd.Normal": "Normálna",
"sabnzbd.Repair": "Opraviť",
"sabnzbd.RepairUnpackDelete": "Opraviť/rozbaliť/vymazať",
"sabnzbd.Size": "Veľkosť",
"sabnzbd.StandbyPC": "Pohotovostný režim PC",
"sabnzbd.Stop": "Stop",
"sabnzbd.RepairUnpack": "Opraviť/rozbaliť",
"sabnzbd.Low": "Nízka",
"sabnzbd.None": "Žiadne",
"sabnzbd.Age": "Vek",
"sabnzbd.Failed": "Neúspešné",
"sabnzbd.HibernatePC": "Hibernovať PC",
"sabnzbd.Paused": "Pozastavené",
"sabnzbd.ShutdownPC": "Vypnúť PC",
"sabnzbd.ShutdownSABnzbd": "Vypnúť SABnzbd",
"search.AllSubcategories": "Všetky podkategórie",
"search.Category": "Kategória",
"search.Download": "Stiahnuť",
"search.Downloading": "Sťahovanie…",
"search.DownloadingNZBToDevice": "Sťahuje sa NZB do zariadenia",
"search.DownloadToDevice": "Stiahnuť do zariadenia",
"search.FailedToDownloadNZB": "Nepodarilo sa stiahnuť NZB",
"search.FailedToSend": "Nepodarilo sa odoslať",
"search.NoSubcategoriesFound": "Nenašli sa žiadne podkategórie",
"search.Results": "Výsledky",
"search.Search": "Vyhľadávanie",
"search.SentTo": "Odoslané {}",
"search.Size": "Veľkosť",
"search.Subcategories": "Podkategórie",
"search.Age": "Vek",
"search.Alphabetical": "Abecedné",
"search.Categories": "Kategórie",
"search.Comments": "Komentáre",
"search.NoCategoriesFound": "Nenašli sa žiadne kategórie",
"search.NoResultsFound": "Nenašli sa žiadne výsledky",
"search.SentNZBData": "Odoslané NZB údaje",
"settings.Account": "Účet",
"settings.AccountDeleted": "Účet zmazaný",
"settings.AccountDescription": "Váš účet LunaSea",
"settings.AccountHelp": "Účet LunaSea",
"settings.AccountSettings": "Nastavenia účtu",
"settings.Add": "Pridať",
"settings.AddHeader": "Pridať hlavičku",
"settings.AddProfile": "Pridať profil",
"settings.AddProfileDescription": "Pridať nový profil",
"settings.AmoledTheme": "AMOLED téma",
"settings.AmoledThemeBorders": "AMOLED Okraje témy",
"settings.AmoledThemeBordersDescription": "Pridanie jemných hraníc v celom UI",
"settings.ApiKey": "API kľúč",
"settings.ApiKeyRequiredMessage": "API kľúč je potrebný na pripojenie k {}",
"settings.AccountDeletedMessage": "Odstránený účet LunaSea",
"settings.AccountHelpHint1": "LunaSea ponúka bezplatný účet na zálohovanie vašej konfigurácie do cloudu, pričom v budúcnosti pribudnú ďalšie funkcie!",
"settings.AddModule": "Pridať modul",
"settings.AddModuleFailed": "Nepodarilo sa pridať modul",
"settings.AddModuleSuccess": "Modul pridaný",
"settings.AddedProfile": "Pridaný profil",
"settings.AllFieldsAreRequired": "Všetky polia sú povinné",
"settings.AmoledThemeDescription": "Čisto čierna tmavá téma",
"settings.ApiKeyRequired": "API kľúč požadovaný",
"settings.AppearanceDescription": "Prispôsobenie vzhľadu a funkcií",
"settings.Appearance": "Vzhľad",
"tautulli.ActivityDetails": "Podrobnosti o aktivite",
"tautulli.BackingUpConfiguration": "Zálohovanie konfigurácie…",
"tautulli.BackingUpConfigurationDescription": "Zálohovanie konfigurácie na pozadí",
"tautulli.BackingUpConfigurationFailed": "Zlyhalo zálohovanie konfigurácie",
"tautulli.BackingUpDatabaseFailed": "Zlyhalo zálohovanie databázy",
"tautulli.BackupConfiguration": "Konfigurácia zálohovania",
"tautulli.Activity": "Aktivita",
"tautulli.Audio": "Audio",
"tautulli.BackingUpDatabase": "Zálohovanie databázy…",
"tautulli.BackingUpDatabaseDescription": "Zálohovanie databázy na pozadí",
"wake_on_lan.MagicPacketSent": "Odoslaný magický balík",
"wake_on_lan.MagicPacketFailedToSend": "Nepodarilo sa odoslať magický balík",
"wake_on_lan.MagicPacketSentMessage": "Váš počítač by sa mal prebúdzať!"
}

View File

@@ -57,6 +57,8 @@
"lunasea.DownloadClient": "İstemciyi İndir",
"lunasea.Edge": "Kenar",
"lunasea.Error": "Hata",
"lunasea.EverySecond": "Her Saniye",
"lunasea.EverySeconds": "Her {} Saniyede Bir",
"lunasea.ExternalModules": "Harici Modüller",
"lunasea.Features": "Özellikler",
"lunasea.Fixes": "Düzeltmeler",
@@ -70,6 +72,7 @@
"lunasea.IncorrectEncryptionKey": "Yanlış şifreleme anahtarı",
"lunasea.Internal": "Dahili",
"lunasea.InvalidFileTypeSelected": "Geçersiz Dosya Türü Seçildi",
"lunasea.Items": "{} Öge",
"lunasea.JustNow": "Az Önce",
"lunasea.Minutes": "{} Dakika",
"lunasea.MinutesAgo": "{} Dakika Önce",
@@ -85,6 +88,7 @@
"lunasea.OneDayAgo": "1 Gün Önce",
"lunasea.OneHour": "1 Saat",
"lunasea.OneHourAgo": "1 Saat Önce",
"lunasea.OneItem": "1 Öge",
"lunasea.OneMinute": "1 Dakika",
"lunasea.OneMinuteAgo": "1 Dakika Önce",
"lunasea.OneMonth": "1 Ay",
@@ -113,6 +117,8 @@
"lunasea.Settings": "Ayarlar",
"lunasea.Stable": "Kararlı",
"lunasea.StartingView": "Başlangıç Görünümü",
"lunasea.ThankYou": "Teşekkürler",
"lunasea.ThankYouMessage": "Açık kaynak topluluğunu desteklediğiniz için teşekkür ederiz!",
"lunasea.Today": "Bugün",
"lunasea.TransactionFailure": "İşlem Hatası",
"lunasea.TryAgain": "Tekrar Deneyin",

View File

@@ -1,5 +1,5 @@
platform :ios, '11.0'
$FirebaseSDKVersion = '10.5.0'
$FirebaseSDKVersion = '10.7.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'

View File

@@ -1,6 +1,6 @@
PODS:
- cloud_firestore (4.4.5):
- Firebase/Firestore (= 10.5.0)
- cloud_firestore (4.5.0):
- Firebase/Firestore (= 10.7.0)
- firebase_core
- Flutter
- nanopb (< 2.30910.0, >= 2.30908.0)
@@ -38,43 +38,43 @@ PODS:
- file_picker (0.0.1):
- DKImagePickerController/PhotoGallery
- Flutter
- Firebase/Auth (10.5.0):
- Firebase/Auth (10.7.0):
- Firebase/CoreOnly
- FirebaseAuth (~> 10.5.0)
- Firebase/CoreOnly (10.5.0):
- FirebaseCore (= 10.5.0)
- Firebase/Firestore (10.5.0):
- FirebaseAuth (~> 10.7.0)
- Firebase/CoreOnly (10.7.0):
- FirebaseCore (= 10.7.0)
- Firebase/Firestore (10.7.0):
- Firebase/CoreOnly
- FirebaseFirestore (~> 10.5.0)
- Firebase/Messaging (10.5.0):
- FirebaseFirestore (~> 10.7.0)
- Firebase/Messaging (10.7.0):
- Firebase/CoreOnly
- FirebaseMessaging (~> 10.5.0)
- Firebase/Storage (10.5.0):
- FirebaseMessaging (~> 10.7.0)
- Firebase/Storage (10.7.0):
- Firebase/CoreOnly
- FirebaseStorage (~> 10.5.0)
- firebase_auth (4.3.0):
- Firebase/Auth (= 10.5.0)
- FirebaseStorage (~> 10.7.0)
- firebase_auth (4.4.0):
- Firebase/Auth (= 10.7.0)
- firebase_core
- Flutter
- firebase_core (2.8.0):
- Firebase/CoreOnly (= 10.5.0)
- firebase_core (2.9.0):
- Firebase/CoreOnly (= 10.7.0)
- Flutter
- firebase_messaging (14.3.0):
- Firebase/Messaging (= 10.5.0)
- firebase_messaging (14.4.0):
- Firebase/Messaging (= 10.7.0)
- firebase_core
- Flutter
- firebase_storage (11.0.16):
- Firebase/Storage (= 10.5.0)
- firebase_storage (11.1.0):
- Firebase/Storage (= 10.7.0)
- firebase_core
- Flutter
- FirebaseAppCheckInterop (10.7.0)
- FirebaseAuth (10.5.0):
- FirebaseAuth (10.7.0):
- FirebaseCore (~> 10.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
- GoogleUtilities/Environment (~> 7.8)
- GTMSessionFetcher/Core (< 4.0, >= 2.1)
- FirebaseAuthInterop (10.7.0)
- FirebaseCore (10.5.0):
- FirebaseCore (10.7.0):
- FirebaseCoreInternal (~> 10.0)
- GoogleUtilities/Environment (~> 7.8)
- GoogleUtilities/Logger (~> 7.8)
@@ -82,20 +82,20 @@ PODS:
- FirebaseCore (~> 10.0)
- FirebaseCoreInternal (10.7.0):
- "GoogleUtilities/NSData+zlib (~> 7.8)"
- FirebaseFirestore (10.5.0):
- FirebaseFirestore/AutodetectLeveldb (= 10.5.0)
- FirebaseFirestore/AutodetectLeveldb (10.5.0):
- FirebaseFirestore (10.7.0):
- FirebaseFirestore/AutodetectLeveldb (= 10.7.0)
- FirebaseFirestore/AutodetectLeveldb (10.7.0):
- FirebaseFirestore/Base
- FirebaseFirestore/WithLeveldb
- FirebaseFirestore/Base (10.5.0)
- FirebaseFirestore/WithLeveldb (10.5.0):
- FirebaseFirestore/Base (10.7.0)
- FirebaseFirestore/WithLeveldb (10.7.0):
- FirebaseFirestore/Base
- FirebaseInstallations (10.7.0):
- FirebaseCore (~> 10.0)
- GoogleUtilities/Environment (~> 7.8)
- GoogleUtilities/UserDefaults (~> 7.8)
- PromisesObjC (~> 2.1)
- FirebaseMessaging (10.5.0):
- FirebaseMessaging (10.7.0):
- FirebaseCore (~> 10.0)
- FirebaseInstallations (~> 10.0)
- GoogleDataTransport (~> 9.2)
@@ -104,7 +104,7 @@ PODS:
- GoogleUtilities/Reachability (~> 7.8)
- GoogleUtilities/UserDefaults (~> 7.8)
- nanopb (< 2.30910.0, >= 2.30908.0)
- FirebaseStorage (10.5.0):
- FirebaseStorage (10.7.0):
- FirebaseAppCheckInterop (~> 10.0)
- FirebaseAuthInterop (~> 10.0)
- FirebaseCore (~> 10.0)
@@ -157,13 +157,13 @@ PODS:
- SDWebImage (5.15.5):
- SDWebImage/Core (= 5.15.5)
- SDWebImage/Core (5.15.5)
- Sentry/HybridSDK (8.3.1):
- SentryPrivate (= 8.3.1)
- Sentry/HybridSDK (8.3.3):
- SentryPrivate (= 8.3.3)
- sentry_flutter (0.0.1):
- Flutter
- FlutterMacOS
- Sentry/HybridSDK (= 8.3.1)
- SentryPrivate (8.3.1)
- Sentry/HybridSDK (= 8.3.3)
- SentryPrivate (8.3.3)
- share_plus (0.0.1):
- Flutter
- shared_preferences_foundation (0.0.1):
@@ -184,7 +184,7 @@ DEPENDENCIES:
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
- firebase_storage (from `.symlinks/plugins/firebase_storage/ios`)
- FirebaseFirestore (from `https://github.com/invertase/firestore-ios-sdk-frameworks.git`, tag `10.5.0`)
- FirebaseFirestore (from `https://github.com/invertase/firestore-ios-sdk-frameworks.git`, tag `10.7.0`)
- Flutter (from `Flutter`)
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
- in_app_purchase_storekit (from `.symlinks/plugins/in_app_purchase_storekit/ios`)
@@ -237,7 +237,7 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/firebase_storage/ios"
FirebaseFirestore:
:git: https://github.com/invertase/firestore-ios-sdk-frameworks.git
:tag: 10.5.0
:tag: 10.7.0
Flutter:
:path: Flutter
flutter_native_splash:
@@ -264,28 +264,28 @@ EXTERNAL SOURCES:
CHECKOUT OPTIONS:
FirebaseFirestore:
:git: https://github.com/invertase/firestore-ios-sdk-frameworks.git
:tag: 10.5.0
:tag: 10.7.0
SPEC CHECKSUMS:
cloud_firestore: 29dafcfe235974cd3907d6212400629838180a16
cloud_firestore: 84f58b426bd8d21a22c4b19d9d18028fc4ff3eb1
DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac
DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179
file_picker: ce3938a0df3cc1ef404671531facef740d03f920
Firebase: 3d6637234ab163e31852834617b4fe1df3b7af6d
firebase_auth: 94ca572cd6a84385096c5a8f6328d5ee6cf84a16
firebase_core: d9c8f891a986a99a60ab81eabb5ef2ea2edcfee1
firebase_messaging: b9ce7e6dbd0c80fca3c8b9ba112eb59e50e178ae
firebase_storage: b6a95fdcb9cc14e4ae44121764e893e08fd65020
Firebase: 0219acf760880eeec8ce479895bd7767466d9f81
firebase_auth: 5984ebaf5463319e304ab1c0966b06994bd1c69a
firebase_core: d85432877e814811e040e7659f9c82faeab66e04
firebase_messaging: 45c0514ca78426630338a42fb7b55af962c7ccd2
firebase_storage: 3419feab3ca832a07bdff5307477e0b9d20eb5f8
FirebaseAppCheckInterop: 8e907eea79958960a8bd2058e067f31e03a7914b
FirebaseAuth: 1028326bcaa7a61391386e74b9078cc558ae14f1
FirebaseAuth: dd64c01631df724b09f33e584625775c52f7d71f
FirebaseAuthInterop: 46201190fe90ef1f581513eb0f9fa3d7820e7d6d
FirebaseCore: 324b8d182d9ff7e3f6d1fa2f04b082d1c7a3e366
FirebaseCore: e317665b9d744727a97e623edbbed009320afdd7
FirebaseCoreExtension: f17247ba8c61e4d3c8d136b5e2de3cb4ac6a85b6
FirebaseCoreInternal: 8845798510aae74703467480f71ac613788d0696
FirebaseFirestore: 41e14a56b72dfdf579790c42b7ac361b30d171f2
FirebaseFirestore: 712ff268d746fc65efb361e9ce2cfeb458f10643
FirebaseInstallations: 59c0e4c7a816a0f76710d83f77e5369b3e45eb96
FirebaseMessaging: 35ecbbc68ff547fca80f9326c9622e79288c7149
FirebaseStorage: 858ba102341232ad8f4e3a457090858200716966
FirebaseMessaging: ac9062bcc35ed56e15a0241d8fd317022499baf8
FirebaseStorage: 4841efa304543e1f9e4ca116c559c7a1ea2a9d0f
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
@@ -299,15 +299,15 @@ SPEC CHECKSUMS:
PromisesObjC: 09985d6d70fbe7878040aa746d78236e6946d2ef
quick_actions_ios: bb09d1c35b4a89f9dbb15487039fa1b983ca375e
SDWebImage: fd7e1a22f00303e058058278639bf6196ee431fe
Sentry: 316f997b2f89557014ae9919f0d0c71e6e43c01e
sentry_flutter: f0e51fac01e46af2e16f0a7458e3014bbc131ff5
SentryPrivate: 63dd9ee25187d20427ab7b5d03054df149912c23
Sentry: 8ffc397d98fe58d693e73959b26ed0eaee55646a
sentry_flutter: 5028afacfa875785cb0e3682aece171fcd9dc0d5
SentryPrivate: bf776a47a131648f5023097215987b40fbd47025
share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68
shared_preferences_foundation: 986fc17f3d3251412d18b0265f9c64113a8c2472
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f
url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4
PODFILE CHECKSUM: e27cc29c7cdd07e9428874a7c32df1ab5677bbc7
PODFILE CHECKSUM: a6733085e951fef104751649a2a2b404da0cbd5f
COCOAPODS: 1.12.0

View File

@@ -7,17 +7,17 @@
objects = {
/* Begin PBXBuildFile section */
0076D3D6D60E83034A1E0D0E /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09FE6EE3FA652F683E30D461 /* Pods_Runner.framework */; };
007DE1E782B48FF895CE4B6C /* Pods_ImageNotification.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BD8A9D1D71899A3A89676B04 /* Pods_ImageNotification.framework */; };
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
849C2933AA1B97340EBE9953 /* Pods_ImageNotification.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 54FFE014976A652BE1BB1494 /* Pods_ImageNotification.framework */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
9C2991242453FE3100B93AB2 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9C2991232453FE3100B93AB2 /* StoreKit.framework */; };
9C7092B325E77E470056AE0B /* NotificationService.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C7092B225E77E470056AE0B /* NotificationService.m */; };
9C7092B725E77E470056AE0B /* ImageNotification.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 9C7092AF25E77E470056AE0B /* ImageNotification.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
C05F88BBB72BB95A8E3AA178 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 737AB4BBCBD47228DD43216B /* Pods_Runner.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -55,14 +55,17 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
09FE6EE3FA652F683E30D461 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
35059A84BC70900306023481 /* Pods-ImageNotification.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ImageNotification.profile.xcconfig"; path = "Target Support Files/Pods-ImageNotification/Pods-ImageNotification.profile.xcconfig"; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
3DAC3CFCC83E7F95ED48FDCA /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
54FFE014976A652BE1BB1494 /* Pods_ImageNotification.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ImageNotification.framework; sourceTree = BUILT_PRODUCTS_DIR; };
737AB4BBCBD47228DD43216B /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
8D3B7B67E1BB6745AD368CC8 /* Pods-ImageNotification.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ImageNotification.debug.xcconfig"; path = "Target Support Files/Pods-ImageNotification/Pods-ImageNotification.debug.xcconfig"; sourceTree = "<group>"; };
7FB5FED64BF621857FFC3D21 /* Pods-ImageNotification.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ImageNotification.debug.xcconfig"; path = "Target Support Files/Pods-ImageNotification/Pods-ImageNotification.debug.xcconfig"; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -70,6 +73,7 @@
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
98E160ABF015B5D4A99B35EF /* Pods-ImageNotification.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ImageNotification.release.xcconfig"; path = "Target Support Files/Pods-ImageNotification/Pods-ImageNotification.release.xcconfig"; sourceTree = "<group>"; };
9C0A396F23E0F00900EC8127 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
9C2991232453FE3100B93AB2 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
9C63379625F08BCB00C44AF3 /* Release-ImageNotification.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Release-ImageNotification.xcconfig"; path = "Flutter/Release-ImageNotification.xcconfig"; sourceTree = "<group>"; };
@@ -78,12 +82,8 @@
9C7092B125E77E470056AE0B /* NotificationService.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NotificationService.h; sourceTree = "<group>"; };
9C7092B225E77E470056AE0B /* NotificationService.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NotificationService.m; sourceTree = "<group>"; };
9C7092B425E77E470056AE0B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
A0A8F8D04139A672EDF6A85F /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
B4DF18831CC2053BF748706B /* Pods-ImageNotification.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ImageNotification.profile.xcconfig"; path = "Target Support Files/Pods-ImageNotification/Pods-ImageNotification.profile.xcconfig"; sourceTree = "<group>"; };
BB3E22A8716743EFBC805A48 /* Pods-ImageNotification.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ImageNotification.release.xcconfig"; path = "Target Support Files/Pods-ImageNotification/Pods-ImageNotification.release.xcconfig"; sourceTree = "<group>"; };
BD8A9D1D71899A3A89676B04 /* Pods_ImageNotification.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ImageNotification.framework; sourceTree = BUILT_PRODUCTS_DIR; };
C4DA1502BC108DB9BB52F223 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
D9B67C19C099711F4CDD87D9 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
B556834D7E7F432CA70496C8 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
C18946FF4D38E61AA09A32B4 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -92,7 +92,7 @@
buildActionMask = 2147483647;
files = (
9C2991242453FE3100B93AB2 /* StoreKit.framework in Frameworks */,
0076D3D6D60E83034A1E0D0E /* Pods_Runner.framework in Frameworks */,
C05F88BBB72BB95A8E3AA178 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -100,7 +100,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
007DE1E782B48FF895CE4B6C /* Pods_ImageNotification.framework in Frameworks */,
849C2933AA1B97340EBE9953 /* Pods_ImageNotification.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -179,8 +179,8 @@
isa = PBXGroup;
children = (
9C2991232453FE3100B93AB2 /* StoreKit.framework */,
BD8A9D1D71899A3A89676B04 /* Pods_ImageNotification.framework */,
09FE6EE3FA652F683E30D461 /* Pods_Runner.framework */,
54FFE014976A652BE1BB1494 /* Pods_ImageNotification.framework */,
737AB4BBCBD47228DD43216B /* Pods_Runner.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@@ -188,12 +188,12 @@
F5D05D221249C73674C5DB0D /* Pods */ = {
isa = PBXGroup;
children = (
8D3B7B67E1BB6745AD368CC8 /* Pods-ImageNotification.debug.xcconfig */,
BB3E22A8716743EFBC805A48 /* Pods-ImageNotification.release.xcconfig */,
B4DF18831CC2053BF748706B /* Pods-ImageNotification.profile.xcconfig */,
D9B67C19C099711F4CDD87D9 /* Pods-Runner.debug.xcconfig */,
A0A8F8D04139A672EDF6A85F /* Pods-Runner.release.xcconfig */,
C4DA1502BC108DB9BB52F223 /* Pods-Runner.profile.xcconfig */,
7FB5FED64BF621857FFC3D21 /* Pods-ImageNotification.debug.xcconfig */,
98E160ABF015B5D4A99B35EF /* Pods-ImageNotification.release.xcconfig */,
35059A84BC70900306023481 /* Pods-ImageNotification.profile.xcconfig */,
3DAC3CFCC83E7F95ED48FDCA /* Pods-Runner.debug.xcconfig */,
C18946FF4D38E61AA09A32B4 /* Pods-Runner.release.xcconfig */,
B556834D7E7F432CA70496C8 /* Pods-Runner.profile.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
@@ -205,7 +205,7 @@
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
5AC1B074EBDF4B45CD073933 /* [CP] Check Pods Manifest.lock */,
E99155ECB0C6A61B1806B7AE /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
@@ -213,8 +213,8 @@
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
9C7092B825E77E470056AE0B /* Embed App Extensions */,
E6A6BAA8A7CCB50967DD02A1 /* [CP] Embed Pods Frameworks */,
8FC36251779B316E672E05BD /* [CP] Copy Pods Resources */,
F68ED0A587233D189FA06BC2 /* [CP] Embed Pods Frameworks */,
425A5744531DA959CC765B08 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@@ -230,7 +230,7 @@
isa = PBXNativeTarget;
buildConfigurationList = 9C7092BC25E77E470056AE0B /* Build configuration list for PBXNativeTarget "ImageNotification" */;
buildPhases = (
1D89D7AEADC332B0D3E033A0 /* [CP] Check Pods Manifest.lock */,
F0E74E09AA58C4BC1371768A /* [CP] Check Pods Manifest.lock */,
9C7092AB25E77E470056AE0B /* Sources */,
9C7092AC25E77E470056AE0B /* Frameworks */,
9C7092AD25E77E470056AE0B /* Resources */,
@@ -308,28 +308,6 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
1D89D7AEADC332B0D3E033A0 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-ImageNotification-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
@@ -345,29 +323,7 @@
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
5AC1B074EBDF4B45CD073933 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
8FC36251779B316E672E05BD /* [CP] Copy Pods Resources */ = {
425A5744531DA959CC765B08 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@@ -400,7 +356,51 @@
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n";
};
E6A6BAA8A7CCB50967DD02A1 /* [CP] Embed Pods Frameworks */ = {
E99155ECB0C6A61B1806B7AE /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
F0E74E09AA58C4BC1371768A /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-ImageNotification-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
F68ED0A587233D189FA06BC2 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (

View File

@@ -1,7 +1,7 @@
/// This file is deprecated and should no longer be actively used.
/// All imports should happen directly and canonical export files will not be used anymore.
export 'state/state.dart';
export 'system/state.dart';
export 'types/loading_state.dart';
export 'database/box.dart';
export 'database/models/profile.dart';

View File

@@ -81,7 +81,6 @@ class LunaBIOS extends StatelessWidget {
supportedLocales: context.supportedLocales,
locale: context.locale,
builder: DevicePreview.appBuilder,
useInheritedMediaQuery: true,
darkTheme: theme.activeTheme(),
theme: theme.activeTheme(),
title: 'LunaSea',

View File

@@ -17,7 +17,7 @@ import 'package:lunasea/modules/sabnzbd.dart';
import 'package:lunasea/modules/nzbget.dart';
import 'package:lunasea/modules/tautulli.dart';
import 'package:lunasea/modules/dashboard/core/state.dart' as dashboard_state;
import 'package:lunasea/modules/dashboard/core/state.dart';
import 'package:lunasea/api/wake_on_lan/wake_on_lan.dart';
import 'package:lunasea/system/flavor.dart';
@@ -436,6 +436,23 @@ extension LunaModuleWebhookExtension on LunaModule {
}
}
String? get webhookDocs {
switch (this) {
case LunaModule.LIDARR:
return 'https://docs.lunasea.app/lunasea/notifications/lidarr';
case LunaModule.RADARR:
return 'https://docs.lunasea.app/lunasea/notifications/radarr';
case LunaModule.SONARR:
return 'https://docs.lunasea.app/lunasea/notifications/sonarr';
case LunaModule.OVERSEERR:
return 'https://docs.lunasea.app/lunasea/notifications/overseerr';
case LunaModule.TAUTULLI:
return 'https://docs.lunasea.app/lunasea/notifications/tautulli';
default:
return null;
}
}
Future<void> handleWebhook(Map<String, dynamic> data) async {
switch (this) {
case LunaModule.LIDARR:
@@ -467,7 +484,7 @@ extension LunaModuleExtension on LunaModule {
case LunaModule.WAKE_ON_LAN:
return null;
case LunaModule.DASHBOARD:
return context.read<dashboard_state.ModuleState>();
return context.read<DashboardState>();
case LunaModule.SETTINGS:
return context.read<SettingsState>();
case LunaModule.SEARCH:

View File

@@ -4,11 +4,11 @@ import 'package:lunasea/modules/dashboard/core/adapters/calendar_starting_size.d
import 'package:lunasea/modules/dashboard/core/adapters/calendar_starting_type.dart';
import 'package:lunasea/modules/dashboard/core/api/api.dart';
import 'package:lunasea/modules/dashboard/core/api/data/abstract.dart';
import 'package:lunasea/state/state.dart';
import 'package:lunasea/system/state.dart';
import 'package:lunasea/vendor.dart';
class ModuleState extends LunaModuleState {
ModuleState() {
class DashboardState extends LunaModuleState {
DashboardState() {
reset();
}

View File

@@ -1,5 +1,4 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:lunasea/widgets/ui.dart';
import 'package:lunasea/system/logger.dart';
@@ -26,8 +25,8 @@ class _State extends State<CalendarPage>
@override
Future<void> loadCallback() async {
context.read<ModuleState>().resetToday();
context.read<ModuleState>().resetUpcoming();
context.read<DashboardState>().resetToday();
context.read<DashboardState>().resetUpcoming();
}
@override
@@ -38,7 +37,7 @@ class _State extends State<CalendarPage>
key: _refreshKey,
onRefresh: loadCallback,
child: FutureBuilder(
future: context.watch<ModuleState>().upcoming,
future: context.watch<DashboardState>().upcoming,
builder: (
BuildContext context,
AsyncSnapshot<Map<DateTime, List<CalendarData>>> snapshot,
@@ -55,7 +54,7 @@ class _State extends State<CalendarPage>
if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData) {
final events = snapshot.data!;
return Selector<ModuleState, CalendarStartingType>(
return Selector<DashboardState, CalendarStartingType>(
selector: (_, s) => s.calendarType,
builder: (context, type, _) {
if (type == CalendarStartingType.CALENDAR)

View File

@@ -44,7 +44,7 @@ class _State extends State<CalendarView> {
void _onDaySelected(DateTime selected, DateTime focused) {
HapticFeedback.selectionClick();
context.read<ModuleState>().selected = selected.floor();
context.read<DashboardState>().selected = selected.floor();
}
@override
@@ -108,10 +108,10 @@ class _State extends State<CalendarView> {
DashboardDatabase.CALENDAR_STARTING_SIZE,
],
builder: (context, _) {
DateTime firstDay = context.watch<ModuleState>().today.subtract(
DateTime firstDay = context.watch<DashboardState>().today.subtract(
Duration(days: DashboardDatabase.CALENDAR_DAYS_PAST.read()),
);
DateTime lastDay = context.watch<ModuleState>().today.add(
DateTime lastDay = context.watch<DashboardState>().today.add(
Duration(days: DashboardDatabase.CALENDAR_DAYS_FUTURE.read()),
);
return SafeArea(
@@ -124,7 +124,7 @@ class _State extends State<CalendarView> {
),
rowHeight: 48.0,
rangeSelectionMode: RangeSelectionMode.disabled,
focusedDay: context.watch<ModuleState>().selected,
focusedDay: context.watch<DashboardState>().selected,
firstDay: firstDay,
lastDay: lastDay,
//events: widget.events,
@@ -142,7 +142,8 @@ class _State extends State<CalendarView> {
startingDayOfWeek:
DashboardDatabase.CALENDAR_STARTING_DAY.read().data,
selectedDayPredicate: (date) {
return date.floor() == context.read<ModuleState>().selected;
return date.floor() ==
context.read<DashboardState>().selected;
},
calendarStyle: CalendarStyle(
markersMaxCount: 1,
@@ -170,7 +171,7 @@ class _State extends State<CalendarView> {
todayTextStyle: dayStyle,
),
onFormatChanged: (format) {
context.read<ModuleState>().calendarFormat = format;
context.read<DashboardState>().calendarFormat = format;
},
daysOfWeekStyle: DaysOfWeekStyle(
weekendStyle: weekdayStyle,
@@ -180,7 +181,7 @@ class _State extends State<CalendarView> {
if (widget.events.isEmpty) return [];
return widget.events[date.floor()] ?? [];
},
calendarFormat: context.watch<ModuleState>().calendarFormat,
calendarFormat: context.watch<DashboardState>().calendarFormat,
availableCalendarFormats: const {
CalendarFormat.month: 'Month',
CalendarFormat.twoWeeks: '2 Weeks',
@@ -228,7 +229,7 @@ class _State extends State<CalendarView> {
}
Widget _calendarList() {
final selected = context.read<ModuleState>().selected;
final selected = context.read<DashboardState>().selected;
final events = widget.events[selected.floor()] ?? [];
if (events.isEmpty) {
return Expanded(

View File

@@ -62,7 +62,7 @@ class _State extends State<ScheduleView> {
keys.sort();
for (final key in keys) {
final selected = context.read<ModuleState>().selected;
final selected = context.read<DashboardState>().selected;
if (key.isBefore(selected) || key.isAtSameMomentAs(selected)) {
offsetOfSelected = offset;
}

View File

@@ -1,5 +1,4 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:lunasea/widgets/ui.dart';
import 'package:lunasea/vendor.dart';
@@ -44,14 +43,14 @@ class _State extends State<SwitchViewAction> with LunaLoadCallbackMixin {
@override
Widget build(BuildContext context) {
return Selector<ModuleState, CalendarStartingType>(
return Selector<DashboardState, CalendarStartingType>(
selector: (_, state) => state.calendarType,
builder: (context, view, _) {
if (_showButton) {
return LunaIconButton.appBar(
icon: view.icon,
onPressed: () {
final state = context.read<ModuleState>();
final state = context.read<DashboardState>();
if (view == CalendarStartingType.CALENDAR)
state.calendarType = CalendarStartingType.SCHEDULE;
else

View File

@@ -30,7 +30,11 @@ class _State extends State<LidarrCatalogue>
Future<void> loadCallback() async {
if (mounted) setState(() => _results = []);
final _api = LidarrAPI.from(LunaProfile.current);
if (mounted) setState(() => {_future = _api.getAllArtists()});
if (mounted) {
setState(() {
_future = _api.getAllArtists();
});
}
}
void _refreshState() => setState(() {});

View File

@@ -46,7 +46,11 @@ class _State extends State<ArtistEditRoute> with LunaScrollControllerMixin {
bottomNavigationBar: _bottomActionBar(),
);
Future<void> _refresh() async => setState(() => {_future = _fetch()});
Future<void> _refresh() async {
setState(() {
_future = _fetch();
});
}
Future<bool> _fetch() async {
final _api = LidarrAPI.from(LunaProfile.current);

View File

@@ -27,7 +27,9 @@ class _State extends State<ArtistAlbumReleasesRoute>
Future<void> loadCallback() async {
if (mounted) setState(() => _results = []);
final _api = LidarrAPI.from(LunaProfile.current);
setState(() => {_future = _api.getReleases(widget.albumId)});
setState(() {
_future = _api.getReleases(widget.albumId);
});
//Clear the search filter using a microtask
Future.microtask(
() => context.read<LidarrState>().searchReleasesFilter = '');

View File

@@ -40,11 +40,15 @@ class _State extends State<StatisticsRoute> with LunaScrollControllerMixin {
}
Future<void> _fetchStatistics(NZBGetAPI api) async {
return await api.getStatistics().then((stats) => {_statistics = stats});
return await api.getStatistics().then((stats) {
_statistics = stats;
});
}
Future<void> _fetchLogs(NZBGetAPI api) async {
return await api.getLogs().then((logs) => {_logs = logs});
return await api.getLogs().then((logs) {
_logs = logs;
});
}
@override

View File

@@ -1,11 +1,11 @@
import 'package:email_validator/email_validator.dart';
import 'package:flutter/material.dart';
import 'package:lunasea/database/tables/lunasea.dart';
import 'package:lunasea/firebase/types.dart';
import 'package:lunasea/modules.dart';
import 'package:lunasea/modules/settings/core/types/header.dart';
import 'package:lunasea/state/state.dart';
import 'package:lunasea/system/state.dart';
import 'package:lunasea/system/localization.dart';
import 'package:lunasea/utils/validator.dart';
import 'package:lunasea/vendor.dart';
import 'package:lunasea/widgets/ui.dart';
import 'package:lunasea/modules/dashboard/core/adapters/calendar_starting_day.dart';
@@ -591,7 +591,7 @@ class SettingsDialogs {
title: 'settings.Email'.tr(),
onSubmitted: (_) => _setValues(true),
validator: (value) {
return EmailValidator.validate(value ?? '')
return LunaValidator().email(value ?? '')
? null
: 'settings.EmailValidation'.tr();
},

View File

@@ -125,9 +125,9 @@ class _State extends State<SettingsHeaderRoute> with LunaScrollControllerMixin {
Future<void> _resetState() async {
switch (widget.module) {
case LunaModule.DASHBOARD:
throw Exception('Dashboard does not have a headers page');
throw Exception('Dashboard does not have a global state');
case LunaModule.EXTERNAL_MODULES:
throw Exception('External modules do not have a headers page');
throw Exception('External modules do not have a global state');
case LunaModule.LIDARR:
return;
case LunaModule.RADARR:
@@ -139,11 +139,11 @@ class _State extends State<SettingsHeaderRoute> with LunaScrollControllerMixin {
case LunaModule.NZBGET:
return;
case LunaModule.SEARCH:
throw Exception('Search does not have a headers page');
throw Exception('Search does not have a global state');
case LunaModule.SETTINGS:
throw Exception('Settings does not have a headers page');
throw Exception('Settings does not have a global state');
case LunaModule.WAKE_ON_LAN:
throw Exception('Wake on LAN does not have a headers page');
throw Exception('Wake on LAN does not have a global state');
case LunaModule.TAUTULLI:
return context.read<TautulliState>().reset();
case LunaModule.OVERSEERR:

View File

@@ -45,9 +45,7 @@ class HeaderUtility {
await _genericHeader(context, headers, indexer);
break;
default:
LunaLogger().warning(
'Unknown case: ${result.item2}',
);
LunaLogger().warning('Unknown case: ${result.item2}');
}
}

View File

@@ -3,7 +3,7 @@ import 'package:lunasea/core.dart';
import 'package:lunasea/firebase/auth.dart';
import 'package:lunasea/utils/validator.dart';
class AccountPasswordResetRoute extends ConsumerStatefulWidget {
class AccountPasswordResetRoute extends StatefulWidget {
const AccountPasswordResetRoute({
Key? key,
}) : super(key: key);
@@ -12,7 +12,7 @@ class AccountPasswordResetRoute extends ConsumerStatefulWidget {
_State createState() => _State();
}
class _State extends ConsumerState<AccountPasswordResetRoute>
class _State extends State<AccountPasswordResetRoute>
with LunaScrollControllerMixin {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
final TextEditingController _emailController = TextEditingController();
@@ -99,7 +99,7 @@ class _State extends ConsumerState<AccountPasswordResetRoute>
}
bool _validateEmailAddress({bool showSnackBarOnFailure = true}) {
if (!ref.watch(validatorProvider).email(_emailController.text)) {
if (!LunaValidator().email(_emailController.text)) {
if (showSnackBarOnFailure) {
showLunaErrorSnackBar(
title: 'settings.InvalidEmail'.tr(),

View File

@@ -4,7 +4,7 @@ import 'package:lunasea/firebase/auth.dart';
import 'package:lunasea/router/routes/settings.dart';
import 'package:lunasea/utils/validator.dart';
class SettingsAccountSignedOutPage extends ConsumerStatefulWidget {
class SettingsAccountSignedOutPage extends StatefulWidget {
final ScrollController scrollController;
const SettingsAccountSignedOutPage({
@@ -16,7 +16,7 @@ class SettingsAccountSignedOutPage extends ConsumerStatefulWidget {
_State createState() => _State();
}
class _State extends ConsumerState<SettingsAccountSignedOutPage> {
class _State extends State<SettingsAccountSignedOutPage> {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
final TextEditingController _emailController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
@@ -124,7 +124,7 @@ class _State extends ConsumerState<SettingsAccountSignedOutPage> {
}
bool _validateEmailAddress({bool showSnackBarOnFailure = true}) {
if (!ref.watch(validatorProvider).email(_emailController.text)) {
if (!LunaValidator().email(_emailController.text)) {
if (showSnackBarOnFailure)
showLunaErrorSnackBar(
title: 'settings.InvalidEmail'.tr(),

View File

@@ -7,7 +7,7 @@ import 'package:lunasea/modules/settings.dart';
import 'package:lunasea/utils/encryption.dart';
import 'package:lunasea/utils/uuid.dart';
class SettingsAccountBackupConfigurationTile extends ConsumerStatefulWidget {
class SettingsAccountBackupConfigurationTile extends StatefulWidget {
const SettingsAccountBackupConfigurationTile({
Key? key,
}) : super(key: key);
@@ -16,7 +16,7 @@ class SettingsAccountBackupConfigurationTile extends ConsumerStatefulWidget {
_State createState() => _State();
}
class _State extends ConsumerState<SettingsAccountBackupConfigurationTile> {
class _State extends State<SettingsAccountBackupConfigurationTile> {
LunaLoadingState _loadingState = LunaLoadingState.INACTIVE;
void updateState(LunaLoadingState state) {
@@ -44,12 +44,10 @@ class _State extends ConsumerState<SettingsAccountBackupConfigurationTile> {
Tuple2<bool, String> _values =
await SettingsDialogs().backupConfiguration(context);
if (_values.item1) {
final encryption = ref.watch(encryptionProvider);
String decrypted = LunaConfig().export();
String encrypted = encryption.encrypt(_values.item2, decrypted);
String encrypted = LunaEncryption().encrypt(_values.item2, decrypted);
int timestamp = DateTime.now().millisecondsSinceEpoch;
String id = ref.watch(uuidProvider).generate();
String id = LunaUUID().generate();
String format = 'MMMM dd, yyyy\nhh:mm:ss a';
String title = DateFormat(format).format(DateTime.now());

View File

@@ -6,7 +6,7 @@ import 'package:lunasea/firebase/storage.dart';
import 'package:lunasea/modules/settings.dart';
import 'package:lunasea/utils/encryption.dart';
class SettingsAccountRestoreConfigurationTile extends ConsumerStatefulWidget {
class SettingsAccountRestoreConfigurationTile extends StatefulWidget {
const SettingsAccountRestoreConfigurationTile({
Key? key,
}) : super(key: key);
@@ -15,7 +15,7 @@ class SettingsAccountRestoreConfigurationTile extends ConsumerStatefulWidget {
_State createState() => _State();
}
class _State extends ConsumerState<SettingsAccountRestoreConfigurationTile> {
class _State extends State<SettingsAccountRestoreConfigurationTile> {
LunaLoadingState _loadingState = LunaLoadingState.INACTIVE;
void updateState(LunaLoadingState state) {
@@ -61,8 +61,7 @@ class _State extends ConsumerState<SettingsAccountRestoreConfigurationTile> {
Tuple2<bool, String> _key = await SettingsDialogs().decryptBackup(context);
if (_key.item1) {
try {
final encryption = ref.watch(encryptionProvider);
String decrypted = encryption.decrypt(_key.item2, encrypted);
String decrypted = LunaEncryption().decrypt(_key.item2, encrypted);
await LunaConfig().import(context, decrypted);
showLunaSuccessSnackBar(
title: 'settings.RestoreFromCloudSuccess'.tr(),

View File

@@ -52,8 +52,8 @@ class _State extends State<ConfigurationDashboardRoute>
Widget _calendarSettingsPage() {
return LunaBlock(
title: 'Calendar Settings',
body: const [TextSpan(text: 'Customize the Unified Calendar')],
title: 'settings.CalendarSettings'.tr(),
body: [TextSpan(text: 'settings.CalendarSettingsDescription'.tr())],
trailing: const LunaIconButton.arrow(),
onTap: SettingsRoutes.CONFIGURATION_DASHBOARD_CALENDAR.go,
);

View File

@@ -46,7 +46,7 @@ class _State extends State<ConfigurationOverseerrRoute>
Widget _enabledToggle() {
return LunaBox.profiles.listenableBuilder(
builder: (context, _) => LunaBlock(
title: 'Enable ${LunaModule.OVERSEERR.title}',
title: 'settings.EnableModule'.tr(args: [LunaModule.OVERSEERR.title]),
trailing: LunaSwitch(
value: LunaProfile.current.overseerrEnabled,
onChanged: (value) {

View File

@@ -66,7 +66,7 @@ class _State extends State<ConfigurationRadarrDefaultPagesRoute>
const _db = RadarrDatabase.NAVIGATION_INDEX_MOVIE_DETAILS;
return _db.listenableBuilder(
builder: (context, _) => LunaBlock(
title: 'Movie Details',
title: 'radarr.MovieDetails'.tr(),
body: [
TextSpan(text: RadarrMovieDetailsNavigationBar.titles[_db.read()]),
],
@@ -89,7 +89,7 @@ class _State extends State<ConfigurationRadarrDefaultPagesRoute>
const _db = RadarrDatabase.NAVIGATION_INDEX_ADD_MOVIE;
return _db.listenableBuilder(
builder: (context, _) => LunaBlock(
title: 'Add Movie',
title: 'radarr.AddMovie'.tr(),
body: [TextSpan(text: RadarrAddMovieNavigationBar.titles[_db.read()])],
trailing:
LunaIconButton(icon: RadarrAddMovieNavigationBar.icons[_db.read()]),
@@ -109,7 +109,7 @@ class _State extends State<ConfigurationRadarrDefaultPagesRoute>
const _db = RadarrDatabase.NAVIGATION_INDEX_SYSTEM_STATUS;
return _db.listenableBuilder(
builder: (context, _) => LunaBlock(
title: 'System Status',
title: 'radarr.SystemStatus'.tr(),
body: [
TextSpan(text: RadarrSystemStatusNavigationBar.titles[_db.read()]),
],

View File

@@ -27,7 +27,7 @@ class _State extends State<ConfigurationRadarrRoute>
Widget _appBar() {
return LunaAppBar(
title: 'Radarr',
title: LunaModule.RADARR.title,
scrollControllers: [scrollController],
);
}
@@ -51,7 +51,7 @@ class _State extends State<ConfigurationRadarrRoute>
Widget _enabledToggle() {
return LunaBox.profiles.listenableBuilder(
builder: (context, _) => LunaBlock(
title: 'Enable ${LunaModule.RADARR.title}',
title: 'settings.EnableModule'.tr(args: [LunaModule.RADARR.title]),
trailing: LunaSwitch(
value: LunaProfile.current.radarrEnabled,
onChanged: (value) {
@@ -66,8 +66,14 @@ class _State extends State<ConfigurationRadarrRoute>
Widget _connectionDetailsPage() {
return LunaBlock(
title: 'Connection Details',
body: const [TextSpan(text: 'Connection Details for Radarr')],
title: 'settings.ConnectionDetails'.tr(),
body: [
TextSpan(
text: 'settings.ConnectionDetailsDescription'.tr(
args: [LunaModule.RADARR.title],
),
),
],
trailing: const LunaIconButton.arrow(),
onTap: SettingsRoutes.CONFIGURATION_RADARR_CONNECTION_DETAILS.go,
);
@@ -84,8 +90,8 @@ class _State extends State<ConfigurationRadarrRoute>
Widget _defaultPagesPage() {
return LunaBlock(
title: 'Default Pages',
body: const [TextSpan(text: 'Set Default Landing Pages')],
title: 'settings.DefaultPages'.tr(),
body: [TextSpan(text: 'settings.DefaultPagesDescription'.tr())],
trailing: const LunaIconButton.arrow(),
onTap: SettingsRoutes.CONFIGURATION_RADARR_DEFAULT_PAGES.go,
);
@@ -95,8 +101,8 @@ class _State extends State<ConfigurationRadarrRoute>
const _db = RadarrDatabase.ADD_DISCOVER_USE_SUGGESTIONS;
return _db.listenableBuilder(
builder: (context, _) => LunaBlock(
title: 'Discover Suggestions',
body: const [TextSpan(text: 'Add Suggested Releases in Discover')],
title: 'radarr.DiscoverSuggestions'.tr(),
body: [TextSpan(text: 'radarr.DiscoverSuggestionsDescription'.tr())],
trailing: LunaSwitch(
value: _db.read(),
onChanged: (value) => _db.update(value),
@@ -109,9 +115,13 @@ class _State extends State<ConfigurationRadarrRoute>
const _db = RadarrDatabase.QUEUE_PAGE_SIZE;
return _db.listenableBuilder(
builder: (context, _) => LunaBlock(
title: 'Queue Size',
title: 'radarr.QueueSize'.tr(),
body: [
TextSpan(text: _db.read() == 1 ? '1 Item' : '${_db.read()} Items')
TextSpan(
text: _db.read() == 1
? 'lunasea.OneItem'.tr()
: 'lunasea.Items'.tr(args: [_db.read().toString()]),
),
],
trailing: const LunaIconButton(icon: Icons.queue_play_next_rounded),
onTap: () async {

View File

@@ -29,7 +29,7 @@ class _State extends State<ConfigurationSABnzbdConnectionDetailsRoute>
Widget _appBar() {
return LunaAppBar(
title: 'Connection Details',
title: 'settings.ConnectionDetails'.tr(),
scrollControllers: [scrollController],
);
}
@@ -104,34 +104,37 @@ class _State extends State<ConfigurationSABnzbdConnectionDetailsRoute>
Widget _testConnection() {
return LunaButton.text(
text: 'Test Connection',
text: 'settings.TestConnection'.tr(),
icon: Icons.wifi_tethering_rounded,
onTap: () async {
LunaProfile _profile = LunaProfile.current;
if (_profile.sabnzbdHost.isEmpty) {
showLunaErrorSnackBar(
title: 'Host Required',
message: 'Host is required to connect to SABnzbd',
title: 'settings.HostRequired'.tr(),
message: 'settings.HostRequiredMessage'
.tr(args: [LunaModule.SABNZBD.title]),
);
return;
}
if (_profile.sabnzbdKey.isEmpty) {
showLunaErrorSnackBar(
title: 'API Key Required',
message: 'API key is required to connect to SABnzbd',
title: 'settings.ApiKeyRequired'.tr(),
message: 'settings.ApiKeyRequiredMessage'
.tr(args: [LunaModule.SABNZBD.title]),
);
return;
}
SABnzbdAPI.from(LunaProfile.current)
.testConnection()
.then((_) => showLunaSuccessSnackBar(
title: 'Connected Successfully',
message: 'SABnzbd is ready to use with LunaSea',
title: 'settings.ConnectedSuccessfully'.tr(),
message: 'settings.ConnectedSuccessfullyMessage'
.tr(args: [LunaModule.SABNZBD.title]),
))
.catchError((error, trace) {
LunaLogger().error('Connection Test Failed', error, trace);
showLunaErrorSnackBar(
title: 'Connection Test Failed',
title: 'settings.ConnectionTestFailed'.tr(),
error: error,
);
});

View File

@@ -27,7 +27,7 @@ class _State extends State<ConfigurationSABnzbdRoute>
PreferredSizeWidget _appBar() {
return LunaAppBar(
title: 'SABnzbd',
title: LunaModule.SABNZBD.title,
scrollControllers: [scrollController],
);
}
@@ -49,7 +49,7 @@ class _State extends State<ConfigurationSABnzbdRoute>
Widget _enabledToggle() {
return LunaBox.profiles.listenableBuilder(
builder: (context, _) => LunaBlock(
title: 'Enable ${LunaModule.SABNZBD.title}',
title: 'settings.EnableModule'.tr(args: [LunaModule.SABNZBD.title]),
trailing: LunaSwitch(
value: LunaProfile.current.sabnzbdEnabled,
onChanged: (value) {

View File

@@ -29,7 +29,7 @@ class _State extends State<ConfigurationSearchAddIndexerRoute>
PreferredSizeWidget _appBar() {
return LunaAppBar(
title: 'Add Indexer',
title: 'search.AddIndexer'.tr(),
scrollControllers: [scrollController],
);
}
@@ -38,20 +38,20 @@ class _State extends State<ConfigurationSearchAddIndexerRoute>
return LunaBottomActionBar(
actions: [
LunaButton.text(
text: 'Add Indexer',
text: 'search.AddIndexer'.tr(),
icon: Icons.add_rounded,
onTap: () async {
if (_indexer.displayName.isEmpty ||
_indexer.host.isEmpty ||
_indexer.apiKey.isEmpty) {
showLunaErrorSnackBar(
title: 'Failed to Add Indexer',
message: 'All fields are required',
title: 'search.FailedToAddIndexer'.tr(),
message: 'settings.AllFieldsAreRequired'.tr(),
);
} else {
LunaBox.indexers.create(_indexer);
showLunaSuccessSnackBar(
title: 'Indexer Added',
title: 'search.IndexerAdded'.tr(),
message: _indexer.displayName,
);
Navigator.of(context).pop();
@@ -77,13 +77,13 @@ class _State extends State<ConfigurationSearchAddIndexerRoute>
Widget _displayName() {
String _name = _indexer.displayName;
return LunaBlock(
title: 'Display Name',
title: 'settings.DisplayName'.tr(),
body: [TextSpan(text: _name.isEmpty ? 'lunasea.NotSet'.tr() : _name)],
trailing: const LunaIconButton.arrow(),
onTap: () async {
Tuple2<bool, String> values = await LunaDialogs().editText(
context,
'Display Name',
'settings.DisplayName'.tr(),
prefill: _name,
);
if (values.item1 && mounted) {
@@ -96,13 +96,13 @@ class _State extends State<ConfigurationSearchAddIndexerRoute>
Widget _apiURL() {
String _host = _indexer.host;
return LunaBlock(
title: 'Indexer API Host',
title: 'search.IndexerAPIHost'.tr(),
body: [TextSpan(text: _host.isEmpty ? 'lunasea.NotSet'.tr() : _host)],
trailing: const LunaIconButton.arrow(),
onTap: () async {
Tuple2<bool, String> values = await LunaDialogs().editText(
context,
'Indexer API Host',
'search.IndexerAPIHost'.tr(),
prefill: _host,
);
if (values.item1 && mounted) {
@@ -115,13 +115,13 @@ class _State extends State<ConfigurationSearchAddIndexerRoute>
Widget _apiKey() {
String _key = _indexer.apiKey;
return LunaBlock(
title: 'Indexer API Key',
title: 'search.IndexerAPIKey'.tr(),
body: [TextSpan(text: _key.isEmpty ? 'lunasea.NotSet'.tr() : _key)],
trailing: const LunaIconButton.arrow(),
onTap: () async {
Tuple2<bool, String> values = await LunaDialogs().editText(
context,
'Indexer API Key',
'search.IndexerAPIKey'.tr(),
prefill: _key,
);
if (values.item1 && mounted) {

View File

@@ -24,8 +24,8 @@ class _State extends State<ConfigurationSearchAddIndexerHeadersRoute>
Widget build(BuildContext context) {
if (widget.indexer == null) {
return InvalidRoutePage(
title: 'Custom Headers',
message: 'Indexer Not Found',
title: 'settings.CustomHeaders'.tr(),
message: 'search.IndexerNotFound'.tr(),
);
}
@@ -39,7 +39,7 @@ class _State extends State<ConfigurationSearchAddIndexerHeadersRoute>
PreferredSizeWidget _appBar() {
return LunaAppBar(
title: 'Custom Headers',
title: 'settings.CustomHeaders'.tr(),
scrollControllers: [scrollController],
);
}
@@ -48,7 +48,7 @@ class _State extends State<ConfigurationSearchAddIndexerHeadersRoute>
return LunaBottomActionBar(
actions: [
LunaButton.text(
text: 'Add Header',
text: 'settings.AddHeader'.tr(),
icon: Icons.add_rounded,
onTap: () async {
await HeaderUtility()
@@ -65,7 +65,7 @@ class _State extends State<ConfigurationSearchAddIndexerHeadersRoute>
controller: scrollController,
children: [
if (widget.indexer!.headers.isEmpty)
LunaMessage.inList(text: 'No Headers Added'),
LunaMessage.inList(text: 'settings.NoHeadersAdded'.tr()),
..._list(),
],
);

View File

@@ -24,23 +24,24 @@ class _State extends State<ConfigurationSearchEditIndexerRoute>
@override
Widget build(BuildContext context) {
if (widget.id < 0)
if (widget.id < 0 || !LunaBox.indexers.contains(widget.id)) {
return InvalidRoutePage(
title: 'Edit Indexer', message: 'Indexer Not Found');
if (!LunaBox.indexers.contains(widget.id))
return InvalidRoutePage(
title: 'Edit Indexer', message: 'Indexer Not Found');
title: 'search.EditIndexer'.tr(),
message: 'search.IndexerNotFound'.tr(),
);
}
return LunaScaffold(
scaffoldKey: _scaffoldKey,
appBar: _appBar() as PreferredSizeWidget?,
appBar: _appBar(),
body: _body(),
bottomNavigationBar: _bottomActionBar(),
);
}
Widget _appBar() {
PreferredSizeWidget _appBar() {
return LunaAppBar(
title: 'Edit Indexer',
title: 'search.EditIndexer'.tr(),
scrollControllers: [scrollController],
);
}
@@ -49,14 +50,16 @@ class _State extends State<ConfigurationSearchEditIndexerRoute>
return LunaBottomActionBar(
actions: [
LunaButton.text(
text: 'Delete Indexer',
text: 'search.DeleteIndexer'.tr(),
icon: Icons.delete_rounded,
color: LunaColours.red,
onTap: () async {
bool result = await SettingsDialogs().deleteIndexer(context);
if (result) {
showLunaSuccessSnackBar(
title: 'Indexer Deleted', message: _indexer!.displayName);
title: 'search.IndexerDeleted'.tr(),
message: _indexer!.displayName,
);
_indexer!.delete();
Navigator.of(context).pop();
}
@@ -86,56 +89,60 @@ class _State extends State<ConfigurationSearchEditIndexerRoute>
}
Widget _displayName() {
String _name = _indexer!.displayName;
return LunaBlock(
title: 'Display Name',
body: [
TextSpan(
text: _indexer?.displayName.isEmpty ?? true
? 'Not Set'
: _indexer!.displayName,
),
],
title: 'settings.DisplayName'.tr(),
body: [TextSpan(text: _name.isEmpty ? 'lunasea.NotSet'.tr() : _name)],
trailing: const LunaIconButton.arrow(),
onTap: () async {
Tuple2<bool, String> values = await LunaDialogs()
.editText(context, 'Display Name', prefill: _indexer!.displayName);
if (values.item1) _indexer!.displayName = values.item2;
Tuple2<bool, String> values = await LunaDialogs().editText(
context,
'settings.DisplayName'.tr(),
prefill: _indexer!.displayName,
);
if (values.item1) {
_indexer!.displayName = values.item2;
}
_indexer!.save();
},
);
}
Widget _apiURL() {
String _host = _indexer!.host;
return LunaBlock(
title: 'Indexer API Host',
body: [
TextSpan(
text: _indexer?.host.isEmpty ?? true ? 'Not Set' : _indexer!.host,
),
],
title: 'search.IndexerAPIHost'.tr(),
body: [TextSpan(text: _host.isEmpty ? 'lunasea.NotSet'.tr() : _host)],
trailing: const LunaIconButton.arrow(),
onTap: () async {
Tuple2<bool, String> values = await LunaDialogs()
.editText(context, 'Indexer API Host', prefill: _indexer!.host);
if (values.item1) _indexer!.host = values.item2;
Tuple2<bool, String> values = await LunaDialogs().editText(
context,
'search.IndexerAPIHost'.tr(),
prefill: _host,
);
if (values.item1 && mounted) {
_indexer!.host = values.item2;
}
_indexer!.save();
},
);
}
Widget _apiKey() {
String _key = _indexer!.apiKey;
return LunaBlock(
title: 'Indexer API Key',
body: [
TextSpan(
text: _indexer?.apiKey.isEmpty ?? true ? 'Not Set' : _indexer!.apiKey,
),
],
title: 'search.IndexerAPIKey'.tr(),
body: [TextSpan(text: _key.isEmpty ? 'lunasea.NotSet'.tr() : _key)],
trailing: const LunaIconButton.arrow(),
onTap: () async {
Tuple2<bool, String> values = await LunaDialogs()
.editText(context, 'Indexer API Key', prefill: _indexer!.apiKey);
if (values.item1) _indexer!.apiKey = values.item2;
Tuple2<bool, String> values = await LunaDialogs().editText(
context,
'search.IndexerAPIKey'.tr(),
prefill: _key,
);
if (values.item1) {
_indexer!.apiKey = values.item2;
}
_indexer!.save();
},
);

View File

@@ -25,8 +25,8 @@ class _State extends State<ConfigurationSearchEditIndexerHeadersRoute>
Widget build(BuildContext context) {
if (widget.id < 0 || !LunaBox.indexers.contains(widget.id)) {
return InvalidRoutePage(
title: 'Custom Headers',
message: 'Indexer Not Found',
title: 'settings.CustomHeaders'.tr(),
message: 'search.IndexerNotFound'.tr(),
);
}
@@ -40,7 +40,7 @@ class _State extends State<ConfigurationSearchEditIndexerHeadersRoute>
Widget _appBar() {
return LunaAppBar(
title: 'Custom Headers',
title: 'settings.CustomHeaders'.tr(),
scrollControllers: [scrollController],
);
}
@@ -49,7 +49,7 @@ class _State extends State<ConfigurationSearchEditIndexerHeadersRoute>
return LunaBottomActionBar(
actions: [
LunaButton.text(
text: 'Add Header',
text: 'settings.AddHeader'.tr(),
icon: Icons.add_rounded,
onTap: () async => HeaderUtility().addHeader(context,
headers: _indexer!.headers, indexer: _indexer),
@@ -68,7 +68,7 @@ class _State extends State<ConfigurationSearchEditIndexerHeadersRoute>
controller: scrollController,
children: [
if (_indexer!.headers.isEmpty)
LunaMessage.inList(text: 'No Headers Added'),
LunaMessage.inList(text: 'settings.NoHeadersAdded'.tr()),
..._list(),
],
);

View File

@@ -21,15 +21,15 @@ class _State extends State<ConfigurationSearchRoute>
Widget build(BuildContext context) {
return LunaScaffold(
scaffoldKey: _scaffoldKey,
appBar: _appBar() as PreferredSizeWidget?,
appBar: _appBar(),
body: _body(),
bottomNavigationBar: _bottomNavigationBar(),
);
}
Widget _appBar() {
PreferredSizeWidget _appBar() {
return LunaAppBar(
title: 'Search',
title: 'search.Search'.tr(),
scrollControllers: [scrollController],
);
}
@@ -38,7 +38,7 @@ class _State extends State<ConfigurationSearchRoute>
return LunaBottomActionBar(
actions: [
LunaButton.text(
text: 'Add Indexer',
text: 'search.AddIndexer'.tr(),
icon: Icons.add_rounded,
onTap: SettingsRoutes.CONFIGURATION_SEARCH_ADD_INDEXER.go,
),
@@ -61,7 +61,7 @@ class _State extends State<ConfigurationSearchRoute>
List<Widget> _indexerSection() {
if (LunaBox.indexers.isEmpty) {
return [const LunaMessage(text: 'No Indexers Found')];
return [LunaMessage(text: 'search.NoIndexersFound'.tr())];
}
return _indexers;
}
@@ -103,8 +103,8 @@ class _State extends State<ConfigurationSearchRoute>
const _db = SearchDatabase.HIDE_XXX;
return _db.listenableBuilder(
builder: (context, _) => LunaBlock(
title: 'Hide Adult Categories',
body: const [TextSpan(text: 'Hide Adult Content')],
title: 'search.HideAdultCategories'.tr(),
body: [TextSpan(text: 'search.HideAdultCategoriesDescription'.tr())],
trailing: LunaSwitch(
value: _db.read(),
onChanged: _db.update,
@@ -117,8 +117,8 @@ class _State extends State<ConfigurationSearchRoute>
const _db = SearchDatabase.SHOW_LINKS;
return _db.listenableBuilder(
builder: (context, _) => LunaBlock(
title: 'Show Links',
body: const [TextSpan(text: 'Show Download and Comments Links')],
title: 'search.ShowLinks'.tr(),
body: [TextSpan(text: 'search.ShowLinksDescription'.tr())],
trailing: LunaSwitch(
value: _db.read(),
onChanged: _db.update,

View File

@@ -29,7 +29,7 @@ class _State extends State<ConfigurationSonarrConnectionDetailsRoute>
PreferredSizeWidget _appBar() {
return LunaAppBar(
title: 'Connection Details',
title: 'settings.ConnectionDetails'.tr(),
scrollControllers: [scrollController],
);
}
@@ -110,15 +110,17 @@ class _State extends State<ConfigurationSonarrConnectionDetailsRoute>
LunaProfile _profile = LunaProfile.current;
if (_profile.sonarrHost.isEmpty) {
showLunaErrorSnackBar(
title: 'Host Required',
message: 'Host is required to connect to Sonarr',
title: 'settings.HostRequired'.tr(),
message: 'settings.HostRequiredMessage'
.tr(args: [LunaModule.SONARR.title]),
);
return;
}
if (_profile.sonarrKey.isEmpty) {
showLunaErrorSnackBar(
title: 'API Key Required',
message: 'API key is required to connect to Sonarr',
title: 'settings.ApiKeyRequired'.tr(),
message: 'settings.ApiKeyRequiredMessage'
.tr(args: [LunaModule.SONARR.title]),
);
return;
}
@@ -130,8 +132,9 @@ class _State extends State<ConfigurationSonarrConnectionDetailsRoute>
),
).system.getStatus().then((_) {
showLunaSuccessSnackBar(
title: 'Connected Successfully',
message: 'Sonarr is ready to use with LunaSea',
title: 'settings.ConnectedSuccessfully'.tr(),
message: 'settings.ConnectedSuccessfullyMessage'
.tr(args: [LunaModule.SONARR.title]),
);
}).catchError((error, trace) {
LunaLogger().error(
@@ -140,7 +143,7 @@ class _State extends State<ConfigurationSonarrConnectionDetailsRoute>
trace,
);
showLunaErrorSnackBar(
title: 'Connection Test Failed',
title: 'settings.ConnectionTestFailed'.tr(),
error: error,
);
});

View File

@@ -21,12 +21,12 @@ class _State extends State<ConfigurationSonarrDefaultOptionsRoute>
Widget build(BuildContext context) {
return LunaScaffold(
scaffoldKey: _scaffoldKey,
appBar: _appBar() as PreferredSizeWidget?,
appBar: _appBar(),
body: _body(),
);
}
Widget _appBar() {
PreferredSizeWidget _appBar() {
return LunaAppBar(
title: 'settings.DefaultOptions'.tr(),
scrollControllers: [scrollController],

View File

@@ -19,12 +19,12 @@ class _State extends State<ConfigurationSonarrDefaultPagesRoute>
Widget build(BuildContext context) {
return LunaScaffold(
scaffoldKey: _scaffoldKey,
appBar: _appBar() as PreferredSizeWidget?,
appBar: _appBar(),
body: _body(),
);
}
Widget _appBar() {
PreferredSizeWidget _appBar() {
return LunaAppBar(
title: 'settings.DefaultPages'.tr(),
scrollControllers: [scrollController],

View File

@@ -20,14 +20,14 @@ class _State extends State<ConfigurationSonarrRoute>
Widget build(BuildContext context) {
return LunaScaffold(
scaffoldKey: _scaffoldKey,
appBar: _appBar() as PreferredSizeWidget?,
appBar: _appBar(),
body: _body(),
);
}
Widget _appBar() {
PreferredSizeWidget _appBar() {
return LunaAppBar(
title: 'Sonarr',
title: LunaModule.SONARR.title,
scrollControllers: [scrollController],
);
}
@@ -50,7 +50,7 @@ class _State extends State<ConfigurationSonarrRoute>
Widget _enabledToggle() {
return LunaBox.profiles.listenableBuilder(
builder: (context, _) => LunaBlock(
title: 'Enable ${LunaModule.SONARR.title}',
title: 'settings.EnableModule'.tr(args: [LunaModule.SONARR.title]),
trailing: LunaSwitch(
value: LunaProfile.current.sonarrEnabled,
onChanged: (value) {
@@ -102,9 +102,13 @@ class _State extends State<ConfigurationSonarrRoute>
const _db = SonarrDatabase.QUEUE_PAGE_SIZE;
return _db.listenableBuilder(
builder: (context, _) => LunaBlock(
title: 'Queue Size',
title: 'sonarr.QueueSize'.tr(),
body: [
TextSpan(text: _db.read() == 1 ? '1 Item' : '${_db.read()} Items')
TextSpan(
text: _db.read() == 1
? 'lunasea.OneItem'.tr()
: 'lunasea.Items'.tr(args: [_db.read().toString()]),
),
],
trailing: const LunaIconButton(icon: Icons.queue_play_next_rounded),
onTap: () async {

View File

@@ -21,15 +21,15 @@ class _State extends State<ConfigurationTautulliConnectionDetailsRoute>
Widget build(BuildContext context) {
return LunaScaffold(
scaffoldKey: _scaffoldKey,
appBar: _appBar() as PreferredSizeWidget?,
appBar: _appBar(),
body: _body(),
bottomNavigationBar: _bottomActionBar(),
);
}
Widget _appBar() {
PreferredSizeWidget _appBar() {
return LunaAppBar(
title: 'Connection Details',
title: 'settings.ConnectionDetails'.tr(),
scrollControllers: [scrollController],
);
}
@@ -110,15 +110,17 @@ class _State extends State<ConfigurationTautulliConnectionDetailsRoute>
LunaProfile _profile = LunaProfile.current;
if (_profile.tautulliHost.isEmpty) {
showLunaErrorSnackBar(
title: 'Host Required',
message: 'Host is required to connect to Tautulli',
title: 'settings.HostRequired'.tr(),
message: 'settings.HostRequiredMessage'
.tr(args: [LunaModule.TAUTULLI.title]),
);
return;
}
if (_profile.tautulliKey.isEmpty) {
showLunaErrorSnackBar(
title: 'API Key Required',
message: 'API key is required to connect to Tautulli',
title: 'settings.ApiKeyRequired'.tr(),
message: 'settings.ApiKeyRequiredMessage'
.tr(args: [LunaModule.TAUTULLI.title]),
);
return;
}
@@ -129,13 +131,14 @@ class _State extends State<ConfigurationTautulliConnectionDetailsRoute>
.miscellaneous
.arnold()
.then((_) => showLunaSuccessSnackBar(
title: 'Connected Successfully',
message: 'Tautulli is ready to use with LunaSea',
title: 'settings.ConnectedSuccessfully'.tr(),
message: 'settings.ConnectedSuccessfullyMessage'
.tr(args: [LunaModule.TAUTULLI.title]),
))
.catchError((error, trace) {
LunaLogger().error('Connection Test Failed', error, trace);
showLunaErrorSnackBar(
title: 'Connection Test Failed',
title: 'settings.ConnectionTestFailed'.tr(),
error: error,
);
});

View File

@@ -26,7 +26,7 @@ class _State extends State<ConfigurationTautulliDefaultPagesRoute>
Widget _appBar() {
return LunaAppBar(
title: 'Default Pages',
title: 'settings.DefaultPages'.tr(),
scrollControllers: [scrollController],
);
}
@@ -67,7 +67,7 @@ class _State extends State<ConfigurationTautulliDefaultPagesRoute>
const _db = TautulliDatabase.NAVIGATION_INDEX_GRAPHS;
return _db.listenableBuilder(
builder: (context, _) => LunaBlock(
title: 'Graphs',
title: 'tautulli.Graphs'.tr(),
body: [TextSpan(text: TautulliGraphsNavigationBar.titles[_db.read()])],
trailing:
LunaIconButton(icon: TautulliGraphsNavigationBar.icons[_db.read()]),
@@ -87,7 +87,7 @@ class _State extends State<ConfigurationTautulliDefaultPagesRoute>
const _db = TautulliDatabase.NAVIGATION_INDEX_LIBRARIES_DETAILS;
return _db.listenableBuilder(
builder: (context, _) => LunaBlock(
title: 'Library Details',
title: 'tautulli.LibraryDetails'.tr(),
body: [
TextSpan(
text: TautulliLibrariesDetailsNavigationBar.titles[_db.read()])
@@ -110,7 +110,7 @@ class _State extends State<ConfigurationTautulliDefaultPagesRoute>
const _db = TautulliDatabase.NAVIGATION_INDEX_MEDIA_DETAILS;
return _db.listenableBuilder(
builder: (context, _) => LunaBlock(
title: 'Media Details',
title: 'tautulli.MediaDetails'.tr(),
body: [
TextSpan(text: TautulliMediaDetailsNavigationBar.titles[_db.read()]),
],
@@ -132,7 +132,7 @@ class _State extends State<ConfigurationTautulliDefaultPagesRoute>
const _db = TautulliDatabase.NAVIGATION_INDEX_USER_DETAILS;
return _db.listenableBuilder(
builder: (context, _) => LunaBlock(
title: 'User Details',
title: 'tautulli.UserDetails'.tr(),
body: [
TextSpan(text: TautulliUserDetailsNavigationBar.titles[_db.read()]),
],

View File

@@ -20,14 +20,14 @@ class _State extends State<ConfigurationTautulliRoute>
Widget build(BuildContext context) {
return LunaScaffold(
scaffoldKey: _scaffoldKey,
appBar: _appBar() as PreferredSizeWidget?,
appBar: _appBar(),
body: _body(),
);
}
Widget _appBar() {
PreferredSizeWidget _appBar() {
return LunaAppBar(
title: 'Tautulli',
title: LunaModule.TAUTULLI.title,
scrollControllers: [scrollController],
);
}
@@ -51,7 +51,7 @@ class _State extends State<ConfigurationTautulliRoute>
Widget _enabledToggle() {
return LunaBox.profiles.listenableBuilder(
builder: (context, _) => LunaBlock(
title: 'Enable ${LunaModule.TAUTULLI.title}',
title: 'settings.EnableModule'.tr(args: [LunaModule.TAUTULLI.title]),
trailing: LunaSwitch(
value: LunaProfile.current.tautulliEnabled,
onChanged: (value) {
@@ -66,9 +66,13 @@ class _State extends State<ConfigurationTautulliRoute>
Widget _connectionDetailsPage() {
return LunaBlock(
title: 'Connection Details',
body: const [
TextSpan(text: 'Connection Details for Tautulli'),
title: 'settings.ConnectionDetails'.tr(),
body: [
TextSpan(
text: 'settings.ConnectionDetailsDescription'.tr(
args: [LunaModule.TAUTULLI.title],
),
),
],
trailing: const LunaIconButton.arrow(),
onTap: SettingsRoutes.CONFIGURATION_TAUTULLI_CONNECTION_DETAILS.go,
@@ -77,8 +81,8 @@ class _State extends State<ConfigurationTautulliRoute>
Widget _defaultPagesPage() {
return LunaBlock(
title: 'Default Pages',
body: const [TextSpan(text: 'Set Default Landing Pages')],
title: 'settings.DefaultPages'.tr(),
body: [TextSpan(text: 'settings.DefaultPagesDescription'.tr())],
trailing: const LunaIconButton.arrow(),
onTap: SettingsRoutes.CONFIGURATION_TAUTULLI_DEFAULT_PAGES.go,
);
@@ -90,8 +94,10 @@ class _State extends State<ConfigurationTautulliRoute>
builder: (context, _) {
String message = _db.read();
return LunaBlock(
title: 'Default Termination Message',
body: [TextSpan(text: message.isEmpty ? 'Not Set' : message)],
title: 'tautulli.DefaultTerminationMessage'.tr(),
body: [
TextSpan(text: message.isEmpty ? 'lunasea.NotSet'.tr() : message),
],
trailing: const LunaIconButton(icon: Icons.videocam_off_rounded),
onTap: () async {
Tuple2<bool, String> result =
@@ -106,11 +112,11 @@ class _State extends State<ConfigurationTautulliRoute>
Widget _activityRefreshRate() {
const _db = TautulliDatabase.REFRESH_RATE;
return _db.listenableBuilder(builder: (context, _) {
String? refreshRate;
if (_db.read() == 1) refreshRate = 'Every Second';
if (_db.read() != 1) refreshRate = 'Every ${_db.read()} Seconds';
String refreshRate = _db.read() == 1
? 'lunasea.EverySecond'.tr()
: 'lunasea.EverySeconds'.tr(args: [_db.read().toString()]);
return LunaBlock(
title: 'Activity Refresh Rate',
title: 'tautulli.ActivityRefreshRate'.tr(),
body: [TextSpan(text: refreshRate)],
trailing: const LunaIconButton(icon: LunaIcons.REFRESH),
onTap: () async {
@@ -125,11 +131,11 @@ class _State extends State<ConfigurationTautulliRoute>
const _db = TautulliDatabase.STATISTICS_STATS_COUNT;
return _db.listenableBuilder(
builder: (context, _) {
String? statisticsItems;
if (_db.read() == 1) statisticsItems = '1 Item';
if (_db.read() != 1) statisticsItems = '${_db.read()} Items';
String statisticsItems = _db.read() == 1
? 'lunasea.OneItem'.tr()
: 'lunasea.Items'.tr(args: [_db.read().toString()]);
return LunaBlock(
title: 'Statistics Item Count',
title: 'tautulli.StatisticsItemCount'.tr(),
body: [TextSpan(text: statisticsItems)],
trailing: const LunaIconButton(icon: Icons.format_list_numbered),
onTap: () async {

View File

@@ -27,7 +27,7 @@ class _State extends State<ConfigurationWakeOnLANRoute>
PreferredSizeWidget _appBar() {
return LunaAppBar(
scrollControllers: [scrollController],
title: 'Wake on LAN',
title: LunaModule.WAKE_ON_LAN.title,
);
}
@@ -47,7 +47,7 @@ class _State extends State<ConfigurationWakeOnLANRoute>
Widget _enabledToggle() {
return LunaBlock(
title: 'Enable Wake on LAN',
title: 'settings.EnableModule'.tr(args: [LunaModule.WAKE_ON_LAN.title]),
trailing: LunaSwitch(
value: LunaProfile.current.wakeOnLANEnabled,
onChanged: (value) {
@@ -63,7 +63,10 @@ class _State extends State<ConfigurationWakeOnLANRoute>
return LunaBlock(
title: 'settings.BroadcastAddress'.tr(),
body: [
TextSpan(text: broadcastAddress == '' ? 'Not Set' : broadcastAddress),
TextSpan(
text:
broadcastAddress == '' ? 'lunasea.NotSet'.tr() : broadcastAddress,
),
],
trailing: const LunaIconButton.arrow(),
onTap: () async {
@@ -85,7 +88,7 @@ class _State extends State<ConfigurationWakeOnLANRoute>
return LunaBlock(
title: 'settings.MACAddress'.tr(),
body: [
TextSpan(text: macAddress == '' ? 'Not Set' : macAddress),
TextSpan(text: macAddress == '' ? 'lunasea.NotSet'.tr() : macAddress),
],
trailing: const LunaIconButton.arrow(),
onTap: () async {

View File

@@ -1 +0,0 @@
export 'pages/ui.dart';

View File

@@ -1,240 +0,0 @@
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:lunasea/core.dart';
import 'package:lunasea/modules/tautulli.dart';
import 'package:lunasea/utils/links.dart';
class DebugMenuUIRoute extends StatefulWidget {
const DebugMenuUIRoute({
Key? key,
}) : super(key: key);
@override
State<DebugMenuUIRoute> createState() => _State();
}
class _State extends State<DebugMenuUIRoute>
with LunaScrollControllerMixin, TickerProviderStateMixin {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
late AnimationController _iconController;
late AnimationController _hideController;
bool _isFabVisible = true;
bool _isFabPaused = false;
@override
void initState() {
super.initState();
_setupIconController();
_setupHideController();
}
@override
void dispose() {
_iconController.dispose();
_hideController.dispose();
scrollController.removeListener(scrollControllerListener);
super.dispose();
}
void scrollControllerListener() {
if (!scrollController.hasClients) return;
switch (scrollController.position.userScrollDirection) {
case ScrollDirection.forward:
if (!_isFabVisible) {
_hideController.forward();
_isFabVisible = true;
}
break;
case ScrollDirection.reverse:
if (_isFabVisible) {
_hideController.reverse();
_isFabVisible = false;
}
break;
case ScrollDirection.idle:
break;
}
}
void _setupIconController() {
_iconController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: LunaUI.ANIMATION_SPEED),
);
}
void _setupHideController() {
_hideController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: LunaUI.ANIMATION_SPEED),
);
_hideController.forward();
scrollController.addListener(scrollControllerListener);
}
Future<void> _toggle(BuildContext context) async {
HapticFeedback.lightImpact();
_isFabPaused ? _iconController.reverse() : _iconController.forward();
setState(() => _isFabPaused = !_isFabPaused);
}
@override
Widget build(BuildContext context) {
return LunaScaffold(
scaffoldKey: _scaffoldKey,
appBar: _appBar() as PreferredSizeWidget?,
body: _body(),
floatingActionButton: _floatingActionButton(),
);
}
Widget _appBar() {
return LunaAppBar(
title: 'settings.DebugMenu'.tr(),
scrollControllers: [scrollController],
);
}
Widget _floatingActionButton() {
return ScaleTransition(
scale: _hideController,
child: InkWell(
child: LunaFloatingActionButtonAnimated(
controller: _iconController,
icon: AnimatedIcons.pause_play,
onPressed: () => _toggle(context),
),
borderRadius: BorderRadius.circular(28.0),
),
);
}
Widget _body() {
return LunaListView(
controller: scrollController,
children: [
..._lunaBlock(),
..._tableContents(),
..._graphs(),
],
);
}
List<TextSpan> _generateBody(int l) =>
List.generate(l, (i) => TextSpan(text: 'Body ${i + 1}'));
List<LunaTableContent> _generateTableContent(int l) => List.generate(l,
(i) => LunaTableContent(title: 'Title ${i + 1}', body: 'Body ${i + 1}'));
List<Widget> _tableContents() {
return [
LunaExpandableListTile(
title: 'Expandable 1',
collapsedSubtitles: _generateBody(2),
expandedTableContent: _generateTableContent(4),
collapsedTrailing: const LunaIconButton(icon: LunaIcons.ARROW_RIGHT),
),
LunaTableCard(content: _generateTableContent(4)),
];
}
List<Widget> _lunaBlock() {
return [
LunaBlock(
title: 'Title 1',
body: _generateBody(1),
bodyLeadingIcons: const [LunaIcons.DOWNLOAD],
leading: const LunaIconButton(icon: LunaIcons.ARROW_RIGHT),
trailing: const LunaIconButton(icon: LunaIcons.ARROW_RIGHT),
),
LunaBlock(
disabled: true,
title: 'Title 1',
body: _generateBody(1),
bodyLeadingIcons: const [LunaIcons.DOWNLOAD],
leading: const LunaIconButton(icon: LunaIcons.ARROW_RIGHT),
trailing: const LunaIconButton(icon: LunaIcons.ARROW_RIGHT),
),
const LunaBlock(
skeletonEnabled: true,
skeletonPoster: true,
skeletonSubtitles: 2,
),
LunaBlock(
title: 'Title 1',
body: _generateBody(2),
posterPlaceholderIcon: LunaIcons.VIDEO_CAM,
posterUrl: LunaLinkedContent.theMovieDB(
'/qLX91FhHWCVrxDVsw0g2UD5c3Zk.jpg',
LinkedContentType.IMAGE_POSTER,
),
backgroundUrl: LunaLinkedContent.theMovieDB(
'/wR3ZbCWM55qbJBcIO7rHm0MB68j.jpg',
LinkedContentType.IMAGE_BACKDROP,
),
onTap: () {},
),
];
}
List<Widget> _graphs() {
TautulliGraphData data = TautulliGraphData.fromJson(json.decode(
'{"categories":["2022-02-05","2022-02-06","2022-02-07","2022-02-08","2022-02-09","2022-02-10","2022-02-11","2022-02-12","2022-02-13","2022-02-14","2022-02-15","2022-02-16","2022-02-17","2022-02-18"],"series":[{"name":"Direct Play","data":[65,27,38,33,31,48,60,33,32,33,20,22,28,68]},{"name":"Direct Stream","data":[0,0,0,0,0,2,0,4,0,0,2,1,0,2]},{"name":"Transcode","data":[9,12,23,12,20,20,9,7,8,5,21,19,23,33]}]}',
));
return [
LunaCard(
context: context,
child: Column(
children: [
SizedBox(
height: TautulliGraphHelper.GRAPH_HEIGHT,
width: MediaQuery.of(context).size.width,
child: Padding(
child: LineChart(
LineChartData(
gridData: TautulliGraphHelper().gridData(),
titlesData: TautulliLineGraphHelper.titlesData(data),
borderData: TautulliGraphHelper().borderData(),
lineBarsData: TautulliLineGraphHelper.lineBarsData(data),
lineTouchData:
TautulliLineGraphHelper.lineTouchData(context, data),
),
),
padding: LunaUI.MARGIN_DEFAULT,
),
),
TautulliGraphHelper().createLegend(data.series!),
],
),
),
LunaCard(
context: context,
child: Column(
children: [
SizedBox(
height: TautulliGraphHelper.GRAPH_HEIGHT,
width: MediaQuery.of(context).size.width,
child: Padding(
child: BarChart(
BarChartData(
alignment: TautulliGraphHelper().chartAlignment(),
gridData: TautulliGraphHelper().gridData(),
titlesData: TautulliGraphHelper().titlesData(data),
borderData: TautulliGraphHelper().borderData(),
barGroups: TautulliBarGraphHelper.barGroups(context, data),
barTouchData:
TautulliBarGraphHelper.barTouchData(context, data),
),
),
padding: LunaUI.MARGIN_DEFAULT,
),
),
TautulliGraphHelper().createLegend(data.series!),
],
),
),
];
}
}

View File

@@ -1,78 +0,0 @@
import 'package:flutter/material.dart';
import 'package:lunasea/core.dart';
import 'package:lunasea/router/routes/settings.dart';
class DebugMenuRoute extends StatefulWidget {
const DebugMenuRoute({
Key? key,
}) : super(key: key);
@override
State<DebugMenuRoute> createState() => _State();
}
class _State extends State<DebugMenuRoute> with LunaScrollControllerMixin {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
return LunaScaffold(
scaffoldKey: _scaffoldKey,
appBar: _appBar(),
body: _body(),
);
}
PreferredSizeWidget _appBar() {
return LunaAppBar(
title: 'settings.DebugMenu'.tr(),
scrollControllers: [scrollController],
);
}
Widget _body() {
return LunaListView(
controller: scrollController,
children: [
LunaBlock(
title: 'UI',
trailing: const LunaIconButton(icon: LunaIcons.ARROW_RIGHT),
onTap: SettingsRoutes.DEBUG_MENU_UI.go,
),
const LunaHeader(text: 'Boxes'),
LunaBlock(
title: 'Clear Alerts Box',
onTap: () async {
await LunaBox.alerts.clear();
showLunaSuccessSnackBar(
title: 'Cleared',
message: 'Cleared Alerts Box',
);
},
),
const LunaHeader(text: 'Toasts'),
LunaBlock(
title: 'Info',
onTap: () async => showLunaInfoSnackBar(
title: 'Info',
message: null,
),
),
LunaBlock(
title: 'Success',
onTap: () async => showLunaSuccessSnackBar(
title: 'Success',
message: null,
),
),
LunaBlock(
title: 'Error',
onTap: () async => showLunaErrorSnackBar(
title: 'Error',
message: null,
),
),
],
);
}
}

View File

@@ -18,14 +18,14 @@ class _State extends State<DonationsThankYouRoute>
Widget build(BuildContext context) {
return LunaScaffold(
scaffoldKey: _scaffoldKey,
appBar: _appBar() as PreferredSizeWidget?,
appBar: _appBar(),
body: _body(),
);
}
Widget _appBar() {
PreferredSizeWidget _appBar() {
return LunaAppBar(
title: 'Donations',
title: 'settings.Donations'.tr(),
scrollControllers: [scrollController],
);
}
@@ -35,11 +35,8 @@ class _State extends State<DonationsThankYouRoute>
controller: scrollController,
children: [
LunaHeader(
text: 'Thank You',
subtitle: [
"Thank you for supporting the open-source community!",
"Donations are never expected or assumed, so thank you for giving back and helping LunaSea remain free, forever!",
].join("\n\n"),
text: 'lunasea.ThankYou'.tr(),
subtitle: 'lunasea.ThankYouMessage'.tr(),
),
],
);

View File

@@ -27,7 +27,7 @@ class _State extends State<DonationsRoute> with LunaScrollControllerMixin {
Widget _appBar() {
return LunaAppBar(
title: 'Donations',
title: 'settings.Donations'.tr(),
scrollControllers: [scrollController],
);
}
@@ -45,7 +45,7 @@ class _State extends State<DonationsRoute> with LunaScrollControllerMixin {
} else {
return LunaMessage.goBack(
context: context,
text: 'Not Available',
text: 'settings.NotAvailable'.tr(),
);
}
},

View File

@@ -28,7 +28,7 @@ class _State extends State<NotificationsRoute> with LunaScrollControllerMixin {
Widget _appBar() {
return LunaAppBar(
title: 'Notifications',
title: 'settings.Notifications'.tr(),
scrollControllers: [scrollController],
);
}
@@ -41,10 +41,9 @@ class _State extends State<NotificationsRoute> with LunaScrollControllerMixin {
future: LunaFirebaseMessaging().areNotificationsAllowed(),
builder: (context, AsyncSnapshot<bool> snapshot) {
if (snapshot.hasData && !snapshot.data!)
return const LunaBanner(
headerText: 'Not Authorized',
bodyText:
'LunaSea is not authorized to show notifications. Please go to your device\'s settings to enable notifications.',
return LunaBanner(
headerText: 'settings.NotAuthorized'.tr(),
bodyText: 'settings.NotAuthorizedMessage'.tr(),
icon: Icons.error_outline_rounded,
iconColor: LunaColours.red,
);
@@ -53,8 +52,8 @@ class _State extends State<NotificationsRoute> with LunaScrollControllerMixin {
),
SettingsBanners.NOTIFICATIONS_MODULE_SUPPORT.banner(),
LunaBlock(
title: 'Getting Started',
body: const [TextSpan(text: 'Information & Setup Instructions')],
title: 'settings.GettingStarted'.tr(),
body: [TextSpan(text: 'settings.GettingStartedDescription'.tr())],
trailing: const LunaIconButton.arrow(),
onTap: LunaLinkedContent.NOTIFICATIONS_DOC.launch,
),

View File

@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:lunasea/core.dart';
import 'package:lunasea/extensions/string/links.dart';
import 'package:lunasea/firebase/auth.dart';
import 'package:lunasea/firebase/messaging.dart';
import 'package:lunasea/system/webhooks.dart';
@@ -21,9 +22,22 @@ class SettingsNotificationsModuleTile extends StatelessWidget {
iconColor: module.color,
bodyText: module.information,
buttons: [
LunaButton.text(
text: 'settings.Device'.tr(),
icon: Icons.devices_rounded,
onTap: () async {
String deviceId = (await LunaFirebaseMessaging().token)!;
await Clipboard.setData(ClipboardData(
text: LunaWebhooks.buildDeviceTokenURL(deviceId, module)));
showLunaInfoSnackBar(
title: 'settings.CopiedURLFor'.tr(args: [module.title]),
message: 'settings.CopiedDeviceURL'.tr(),
);
},
),
if (LunaFirebaseAuth().isSignedIn)
LunaButton.text(
text: 'User',
text: 'settings.User'.tr(),
icon: Icons.person_rounded,
onTap: () async {
if (!LunaFirebaseAuth().isSignedIn) return;
@@ -31,23 +45,16 @@ class SettingsNotificationsModuleTile extends StatelessWidget {
await Clipboard.setData(ClipboardData(
text: LunaWebhooks.buildUserTokenURL(userId, module)));
showLunaInfoSnackBar(
title: 'Copied URL for ${module.title}',
message: 'Copied your user-based URL to the clipboard',
title: 'settings.CopiedURLFor'.tr(args: [module.title]),
message: 'settings.CopiedUserURL'.tr(),
);
},
),
LunaButton.text(
text: 'Device',
icon: Icons.devices_rounded,
onTap: () async {
String deviceId = (await LunaFirebaseMessaging().token)!;
await Clipboard.setData(ClipboardData(
text: LunaWebhooks.buildDeviceTokenURL(deviceId, module)));
showLunaInfoSnackBar(
title: 'Copied URL for ${module.title}',
message: 'Copied your device-based URL to the clipboard',
);
},
text: 'settings.Documentation'.tr(),
icon: LunaIcons.DOCUMENTATION,
color: LunaColours.blue,
onTap: module.webhookDocs!.openLink,
),
],
);

View File

@@ -3,7 +3,6 @@ import 'package:lunasea/core.dart';
import 'package:lunasea/firebase/core.dart';
import 'package:lunasea/firebase/messaging.dart';
import 'package:lunasea/router/routes/settings.dart';
import 'package:lunasea/system/flavor.dart';
import 'package:lunasea/system/in_app_purchase/in_app_purchase.dart';
class SettingsRoute extends StatefulWidget {
@@ -22,7 +21,7 @@ class _State extends State<SettingsRoute> with LunaScrollControllerMixin {
Widget build(BuildContext context) {
return LunaScaffold(
scaffoldKey: _scaffoldKey,
appBar: _appBar() as PreferredSizeWidget?,
appBar: _appBar(),
drawer: _drawer(),
body: _body(),
);
@@ -30,7 +29,7 @@ class _State extends State<SettingsRoute> with LunaScrollControllerMixin {
Widget _drawer() => LunaDrawer(page: LunaModule.SETTINGS.key);
Widget _appBar() {
PreferredSizeWidget _appBar() {
return LunaAppBar(
useDrawer: true,
scrollControllers: [scrollController],
@@ -88,13 +87,6 @@ class _State extends State<SettingsRoute> with LunaScrollControllerMixin {
trailing: const LunaIconButton(icon: Icons.settings_rounded),
onTap: SettingsRoutes.SYSTEM.go,
),
if (LunaFlavor.CANDIDATE.isRunningFlavor())
LunaBlock(
title: 'settings.DebugMenu'.tr(),
body: [TextSpan(text: 'settings.DebugMenuDescription'.tr())],
trailing: const LunaIconButton(icon: Icons.bug_report_rounded),
onTap: SettingsRoutes.DEBUG_MENU.go,
),
],
);
}

View File

@@ -26,14 +26,14 @@ class _State extends State<SystemRoute> with LunaScrollControllerMixin {
Widget build(BuildContext context) {
return LunaScaffold(
scaffoldKey: _scaffoldKey,
appBar: _appBar() as PreferredSizeWidget?,
appBar: _appBar(),
body: _body(),
);
}
Widget _appBar() {
PreferredSizeWidget _appBar() {
return LunaAppBar(
title: 'System',
title: 'settings.System'.tr(),
scrollControllers: [scrollController],
);
}
@@ -48,7 +48,7 @@ class _State extends State<SystemRoute> with LunaScrollControllerMixin {
const SettingsSystemBackupRestoreRestoreTile(),
LunaDivider(),
_logs(),
if (LunaImageCache.isSupported) _clearImageCache(),
_clearImageCache(),
_clearConfiguration(),
],
);
@@ -56,8 +56,8 @@ class _State extends State<SystemRoute> with LunaScrollControllerMixin {
Widget _logs() {
return LunaBlock(
title: 'Logs',
body: const [TextSpan(text: 'View, Export, and Clear Logs')],
title: 'settings.Logs'.tr(),
body: [TextSpan(text: 'settings.LogsDescription'.tr())],
trailing: const LunaIconButton(icon: Icons.developer_mode_rounded),
onTap: SettingsRoutes.SYSTEM_LOGS.go,
);
@@ -65,17 +65,24 @@ class _State extends State<SystemRoute> with LunaScrollControllerMixin {
Widget _clearImageCache() {
return LunaBlock(
title: 'Clear Image Cache',
body: const [TextSpan(text: 'Clear Cached Images From the Disk')],
title: 'settings.ClearImageCache'.tr(),
body: [TextSpan(text: 'settings.ClearImageCacheDescription'.tr())],
trailing: const LunaIconButton(icon: Icons.image_not_supported_rounded),
onTap: () async {
bool result = await SettingsDialogs().clearImageCache(context);
if (result) {
LunaImageCache().clear();
showLunaSuccessSnackBar(
title: 'Image Cache Cleared',
message: 'Your image cache has been cleared',
);
result = await LunaImageCache().clear();
if (result) {
showLunaSuccessSnackBar(
title: 'settings.ImageCacheCleared'.tr(),
message: 'settings.ImageCacheClearedDescription'.tr(),
);
} else {
showLunaErrorSnackBar(
title: 'settings.FailedToClearImageCache'.tr(),
message: 'settings.FailedToClearImageCacheDescription'.tr(),
);
}
}
},
);
@@ -83,8 +90,8 @@ class _State extends State<SystemRoute> with LunaScrollControllerMixin {
Widget _clearConfiguration() {
return LunaBlock(
title: 'Clear Configuration',
body: const [TextSpan(text: 'Clean Slate')],
title: 'settings.ClearConfiguration'.tr(),
body: [TextSpan(text: 'settings.CleanSlate'.tr())],
trailing: const LunaIconButton(icon: Icons.delete_sweep_rounded),
onTap: () async {
bool result = await SettingsDialogs().clearConfiguration(context);
@@ -93,8 +100,8 @@ class _State extends State<SystemRoute> with LunaScrollControllerMixin {
if (LunaFirebase.isSupported) LunaFirebaseAuth().signOut();
LunaState.reset(context);
showLunaSuccessSnackBar(
title: 'Configuration Cleared',
message: 'Your configuration has been cleared',
title: 'settings.ConfigurationCleared'.tr(),
message: 'settings.ConfigurationClearedDescription'.tr(),
);
}
},

View File

@@ -5,28 +5,27 @@ import 'package:lunasea/modules/settings.dart';
import 'package:lunasea/system/filesystem/filesystem.dart';
import 'package:lunasea/utils/encryption.dart';
class SettingsSystemBackupRestoreBackupTile extends ConsumerWidget {
class SettingsSystemBackupRestoreBackupTile extends StatelessWidget {
const SettingsSystemBackupRestoreBackupTile({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
Widget build(BuildContext context) {
return LunaBlock(
title: 'settings.BackupToDevice'.tr(),
body: [TextSpan(text: 'settings.BackupToDeviceDescription'.tr())],
trailing: const LunaIconButton(icon: Icons.upload_rounded),
onTap: () async => _backup(context, ref),
onTap: () async => _backup(context),
);
}
Future<void> _backup(BuildContext context, WidgetRef ref) async {
Future<void> _backup(BuildContext context) async {
try {
final _values = await SettingsDialogs().backupConfiguration(context);
if (_values.item1) {
final encryption = ref.watch(encryptionProvider);
String data = LunaConfig().export();
String encrypted = encryption.encrypt(_values.item2, data);
String encrypted = LunaEncryption().encrypt(_values.item2, data);
String name = DateFormat('y-MM-dd kk-mm-ss').format(DateTime.now());
bool result = await LunaFileSystem().save(
context,

View File

@@ -8,14 +8,14 @@ import 'package:lunasea/vendor.dart';
import 'package:lunasea/widgets/sheets/changelog/sheet.dart';
import 'package:lunasea/widgets/ui.dart';
class BuildDetails extends ConsumerStatefulWidget {
class BuildDetails extends StatefulWidget {
const BuildDetails({Key? key}) : super(key: key);
@override
ConsumerState<BuildDetails> createState() => _State();
State<BuildDetails> createState() => _State();
}
class _State extends ConsumerState<BuildDetails> {
class _State extends State<BuildDetails> {
Future<PackageInfo> packageInfo = PackageInfo.fromPlatform();
Future<Tuple2<bool, int?>> checkUpdates = LunaBuild().isLatestBuildNumber();
@@ -69,7 +69,7 @@ class _State extends ConsumerState<BuildDetails> {
if (updates.hasError) {
return LunaButton.text(
icon: LunaIcons.ERROR,
text: 'Error',
text: 'lunasea.Error'.tr(),
);
}
if (updates.connectionState == ConnectionState.done && updates.hasData) {

View File

@@ -6,25 +6,25 @@ import 'package:lunasea/system/filesystem/file.dart';
import 'package:lunasea/system/filesystem/filesystem.dart';
import 'package:lunasea/utils/encryption.dart';
class SettingsSystemBackupRestoreRestoreTile extends ConsumerWidget {
class SettingsSystemBackupRestoreRestoreTile extends StatelessWidget {
const SettingsSystemBackupRestoreRestoreTile({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
Widget build(BuildContext context) {
return LunaBlock(
title: 'settings.RestoreFromDevice'.tr(),
body: [TextSpan(text: 'settings.RestoreFromDeviceDescription'.tr())],
trailing: const LunaIconButton(icon: Icons.download_rounded),
onTap: () async => _restore(context, ref),
onTap: () async => _restore(context),
);
}
Future<void> _restore(BuildContext context, WidgetRef ref) async {
Future<void> _restore(BuildContext context) async {
try {
LunaFile? file = await LunaFileSystem().read(context, ['lunasea']);
if (file != null) await _decryptBackup(context, ref, file);
if (file != null) await _decryptBackup(context, file);
} catch (error, stack) {
LunaLogger().error('Failed to restore device backup', error, stack);
showLunaErrorSnackBar(
@@ -36,15 +36,13 @@ class SettingsSystemBackupRestoreRestoreTile extends ConsumerWidget {
Future<void> _decryptBackup(
BuildContext context,
WidgetRef ref,
LunaFile file,
) async {
Tuple2<bool, String> _key = await SettingsDialogs().decryptBackup(context);
if (_key.item1) {
final encryption = ref.watch(encryptionProvider);
String encrypted = String.fromCharCodes(file.data);
try {
String decrypted = encryption.decrypt(_key.item2, encrypted);
String decrypted = LunaEncryption().decrypt(_key.item2, encrypted);
await LunaConfig().import(context, decrypted);
showLunaSuccessSnackBar(
title: 'settings.RestoreFromCloudSuccess'.tr(),
@@ -56,7 +54,7 @@ class SettingsSystemBackupRestoreRestoreTile extends ConsumerWidget {
message: 'lunasea.IncorrectEncryptionKey'.tr(),
showButton: true,
buttonText: 'lunasea.Retry'.tr(),
buttonOnPressed: () async => _decryptBackup(context, ref, file),
buttonOnPressed: () async => _decryptBackup(context, file),
);
}
}

View File

@@ -24,14 +24,14 @@ class _State extends State<SystemLogsDetailsRoute>
Widget build(BuildContext context) {
return LunaScaffold(
scaffoldKey: _scaffoldKey,
appBar: _appBar() as PreferredSizeWidget?,
appBar: _appBar(),
body: _body(),
);
}
Widget _appBar() {
PreferredSizeWidget _appBar() {
return LunaAppBar(
title: '${widget.type?.title ?? 'All'} Logs',
title: 'settings.Logs'.tr(),
scrollControllers: [scrollController],
);
}
@@ -42,7 +42,7 @@ class _State extends State<SystemLogsDetailsRoute>
if (logs.isEmpty) {
return LunaMessage.goBack(
context: context,
text: 'No Logs Found',
text: 'settings.NoLogsFound'.tr(),
);
}
return LunaListViewBuilder(

View File

@@ -22,15 +22,15 @@ class _State extends State<SystemLogsRoute> with LunaScrollControllerMixin {
Widget build(BuildContext context) {
return LunaScaffold(
scaffoldKey: _scaffoldKey,
appBar: _appBar() as PreferredSizeWidget?,
appBar: _appBar(),
body: _body(),
bottomNavigationBar: _bottomActionBar(),
);
}
Widget _appBar() {
PreferredSizeWidget _appBar() {
return LunaAppBar(
title: 'Logs',
title: 'settings.Logs'.tr(),
scrollControllers: [scrollController],
);
}
@@ -49,8 +49,8 @@ class _State extends State<SystemLogsRoute> with LunaScrollControllerMixin {
controller: scrollController,
children: [
LunaBlock(
title: 'All Logs',
body: const [TextSpan(text: 'View Logs of All Types')],
title: 'settings.AllLogs'.tr(),
body: [TextSpan(text: 'settings.AllLogsDescription'.tr())],
trailing: const LunaIconButton(icon: Icons.developer_mode_rounded),
onTap: () async => _viewLogs(null),
),
@@ -95,7 +95,7 @@ class _State extends State<SystemLogsRoute> with LunaScrollControllerMixin {
Widget _clearLogs() {
return LunaButton.text(
text: 'Clear',
text: 'settings.Clear'.tr(),
icon: LunaIcons.DELETE,
color: LunaColours.red,
onTap: () async {
@@ -103,8 +103,8 @@ class _State extends State<SystemLogsRoute> with LunaScrollControllerMixin {
if (result) {
LunaLogger().clear();
showLunaSuccessSnackBar(
title: 'Logs Cleared',
message: 'All recorded logs have been cleared',
title: 'settings.LogsCleared'.tr(),
message: 'settings.LogsClearedDescription'.tr(),
);
}
},
@@ -114,20 +114,16 @@ class _State extends State<SystemLogsRoute> with LunaScrollControllerMixin {
Widget _exportLogs() {
return Builder(
builder: (context) => LunaButton.text(
text: 'Export',
text: 'settings.Export'.tr(),
icon: LunaIcons.DOWNLOAD,
onTap: () async {
showLunaInfoSnackBar(
title: 'Exporting Logs',
message: 'Please wait...',
);
String data = await LunaLogger().export();
bool result = await LunaFileSystem()
.save(context, 'logs.json', utf8.encode(data));
if (result)
showLunaSuccessSnackBar(
title: 'Saved Logs',
message: 'Logs have been successfully saved');
title: 'settings.ExportedLogs'.tr(),
message: 'settings.ExportedLogsMessage'.tr());
},
),
);

View File

@@ -39,11 +39,11 @@ class SettingsSystemLogTile extends StatelessWidget {
],
expandedTableContent: [
if (log.className != null && log.className!.isNotEmpty)
LunaTableContent(title: 'Class', body: log.className),
LunaTableContent(title: 'settings.Class'.tr(), body: log.className),
if (log.methodName != null && log.methodName!.isNotEmpty)
LunaTableContent(title: 'Method', body: log.methodName),
LunaTableContent(title: 'settings.Method'.tr(), body: log.methodName),
if (log.error != null && log.error!.isNotEmpty)
LunaTableContent(title: 'Exception', body: log.error),
LunaTableContent(title: 'settings.Exception'.tr(), body: log.error),
],
);
}

View File

@@ -100,13 +100,13 @@ class _State extends State<SonarrUpcomingRoute>
List<List<Widget>> _episodeWidgets = [];
_episodeMap.keys.toList()
..sort()
..forEach((key) => {
_episodeWidgets.add(_buildDay(
(_episodeMap[key]!['date'] as String?),
(_episodeMap[key]!['entries'] as List).cast<SonarrCalendar>(),
series,
)),
});
..forEach((key) {
_episodeWidgets.add(_buildDay(
(_episodeMap[key]!['date'] as String?),
(_episodeMap[key]!['entries'] as List).cast<SonarrCalendar>(),
series,
));
});
// Return the list
return LunaListView(
controller: SonarrNavigationBar.scrollControllers[1],

View File

@@ -94,7 +94,7 @@ mixin LunaRoutesMixin on Enum {
queryParams: queryParams,
);
}
return LunaRouter.router.pushNamed(
LunaRouter.router.pushNamed(
_routeName,
extra: extra,
params: params,

View File

@@ -49,8 +49,6 @@ import 'package:lunasea/modules/settings/routes/configuration_tautulli/pages/def
import 'package:lunasea/modules/settings/routes/configuration_tautulli/pages/headers.dart';
import 'package:lunasea/modules/settings/routes/configuration_tautulli/route.dart';
import 'package:lunasea/modules/settings/routes/configuration_wake_on_lan/route.dart';
import 'package:lunasea/modules/settings/routes/debug_menu/pages/ui.dart';
import 'package:lunasea/modules/settings/routes/debug_menu/route.dart';
import 'package:lunasea/modules/settings/routes/donations/pages/thank_you.dart';
import 'package:lunasea/modules/settings/routes/donations/route.dart';
import 'package:lunasea/modules/settings/routes/notifications/route.dart';
@@ -114,8 +112,6 @@ enum SettingsRoutes with LunaRoutesMixin {
CONFIGURATION_TAUTULLI_CONNECTION_DETAILS_HEADERS('headers'),
CONFIGURATION_TAUTULLI_DEFAULT_PAGES('default_pages'),
CONFIGURATION_WAKE_ON_LAN('wake_on_lan'),
DEBUG_MENU('debug_menu'),
DEBUG_MENU_UI('ui'),
DONATIONS('donations'),
DONATIONS_THANK_YOU('thank_you'),
NOTIFICATIONS('notifications'),
@@ -269,10 +265,6 @@ enum SettingsRoutes with LunaRoutesMixin {
return route(widget: const ConfigurationTautulliDefaultPagesRoute());
case SettingsRoutes.CONFIGURATION_WAKE_ON_LAN:
return route(widget: const ConfigurationWakeOnLANRoute());
case SettingsRoutes.DEBUG_MENU:
return route(widget: const DebugMenuRoute());
case SettingsRoutes.DEBUG_MENU_UI:
return route(widget: const DebugMenuUIRoute());
case SettingsRoutes.DONATIONS:
return route(widget: const DonationsRoute());
case SettingsRoutes.DONATIONS_THANK_YOU:
@@ -302,7 +294,6 @@ enum SettingsRoutes with LunaRoutesMixin {
return [
SettingsRoutes.ACCOUNT.routes,
SettingsRoutes.CONFIGURATION.routes,
SettingsRoutes.DEBUG_MENU.routes,
SettingsRoutes.DONATIONS.routes,
SettingsRoutes.NOTIFICATIONS.routes,
SettingsRoutes.PROFILES.routes,
@@ -416,10 +407,6 @@ enum SettingsRoutes with LunaRoutesMixin {
SettingsRoutes
.CONFIGURATION_TAUTULLI_CONNECTION_DETAILS_HEADERS.routes,
];
case SettingsRoutes.DEBUG_MENU:
return [
SettingsRoutes.DEBUG_MENU_UI.routes,
];
case SettingsRoutes.DONATIONS:
return [
SettingsRoutes.DONATIONS_THANK_YOU.routes,

View File

@@ -1,27 +0,0 @@
import 'package:lunasea/api/sabnzbd/api.dart';
import 'package:lunasea/database/box.dart';
import 'package:lunasea/state/sabnzbd/config.dart';
import 'package:lunasea/vendor.dart';
final apiProvider =
Provider.autoDispose.family<SABnzbdAPI, String>((ref, uuid) {
final db = ref.watch(configProvider(uuid));
// A database update was triggered
if (db.hasValue) {
final config = db.value!;
return SABnzbdAPI(
host: config.host,
apiKey: config.apiKey,
headers: config.headers,
);
}
// Initial load
final config = LunaBox.profiles.read(uuid)!;
return SABnzbdAPI(
host: config.sabnzbdHost,
apiKey: config.sabnzbdKey,
headers: config.sabnzbdHeaders,
);
});

View File

@@ -1,32 +0,0 @@
import 'package:lunasea/database/box.dart';
import 'package:lunasea/database/models/profile.dart';
import 'package:lunasea/vendor.dart';
class _DB {
final bool enabled;
final String host;
final String apiKey;
final Map<String, String> headers;
_DB(
this.enabled, {
this.host = '',
this.apiKey = '',
this.headers = const {},
});
}
final configProvider = StreamProvider.family<_DB, String>((ref, uuid) async* {
final box = LunaBox.profiles.watch(uuid);
await for (final event in box) {
if (event.deleted) yield _DB(false);
LunaProfile profile = event.value;
yield _DB(
profile.sabnzbdEnabled,
host: profile.sabnzbdHost,
apiKey: profile.sabnzbdKey,
headers: profile.sabnzbdHeaders,
);
}
});

View File

@@ -9,6 +9,6 @@ abstract class LunaImageCache {
factory LunaImageCache() => getImageCache();
void initialize();
Future<void> clear();
Future<bool> clear();
dynamic get instance;
}

View File

@@ -21,11 +21,15 @@ class IO implements LunaImageCache {
CacheManager get instance => _cache;
@override
Future<void> clear() async => _cache.emptyCache();
Future<bool> clear() async {
await _cache.emptyCache();
PaintingBinding.instance.imageCache.clear();
return true;
}
@override
void initialize() {
ImageCache().maximumSize = 1000;
ImageCache().maximumSizeBytes = 128 << 20;
PaintingBinding.instance.imageCache.maximumSize = 1000;
PaintingBinding.instance.imageCache.maximumSizeBytes = 128 << 20;
}
}

View File

@@ -5,13 +5,11 @@ import 'package:lunasea/widgets/ui.dart';
const FLAVOR_EDGE = 'edge';
const FLAVOR_BETA = 'beta';
const FLAVOR_CANDIDATE = 'candidate';
const FLAVOR_STABLE = 'stable';
enum LunaFlavor {
EDGE(FLAVOR_EDGE),
BETA(FLAVOR_BETA),
CANDIDATE(FLAVOR_CANDIDATE),
STABLE(FLAVOR_STABLE);
final String key;
@@ -23,8 +21,6 @@ enum LunaFlavor {
return LunaFlavor.EDGE;
case FLAVOR_BETA:
return LunaFlavor.BETA;
case FLAVOR_CANDIDATE:
return LunaFlavor.CANDIDATE;
case FLAVOR_STABLE:
return LunaFlavor.STABLE;
}
@@ -35,13 +31,10 @@ enum LunaFlavor {
static bool get isEdge => current == LunaFlavor.EDGE;
static bool get isBeta => current == LunaFlavor.BETA;
static bool get isCandidate => current == LunaFlavor.CANDIDATE;
static bool get isStable => current == LunaFlavor.STABLE;
}
extension LunaFlavorExtension on LunaFlavor {
// Returns true if the running build's flavor is "lower" than or equal to the called-on flavor.
/// For example, a running build of `beta` is lower than `candidate` but is not lower than `edge`.
bool isRunningFlavor() {
LunaFlavor flavor = LunaFlavor.current;
if (flavor == this) return true;
@@ -51,8 +44,6 @@ extension LunaFlavorExtension on LunaFlavor {
return false;
case LunaFlavor.BETA:
return flavor == LunaFlavor.EDGE;
case LunaFlavor.CANDIDATE:
return flavor == LunaFlavor.EDGE || flavor == LunaFlavor.BETA;
case LunaFlavor.STABLE:
return true;
}
@@ -65,8 +56,6 @@ extension LunaFlavorExtension on LunaFlavor {
return '$base/${this.key}/';
case LunaFlavor.BETA:
return '$base/${this.key}/';
case LunaFlavor.CANDIDATE:
return '$base/${this.key}/';
case LunaFlavor.STABLE:
return '$base/${this.key}/';
}
@@ -78,8 +67,6 @@ extension LunaFlavorExtension on LunaFlavor {
return 'lunasea.Edge'.tr();
case LunaFlavor.BETA:
return 'lunasea.Beta'.tr();
case LunaFlavor.CANDIDATE:
return 'lunasea.Candidate'.tr();
case LunaFlavor.STABLE:
return 'lunasea.Stable'.tr();
}
@@ -90,8 +77,6 @@ extension LunaFlavorExtension on LunaFlavor {
case LunaFlavor.EDGE:
return LunaColours.red;
case LunaFlavor.BETA:
return LunaColours.orange;
case LunaFlavor.CANDIDATE:
return LunaColours.blue;
case LunaFlavor.STABLE:
return LunaColours.accent;

View File

@@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:lunasea/state/state.dart';
import 'package:lunasea/system/state.dart';
import 'package:lunasea/system/flavor.dart';
import 'package:lunasea/vendor.dart';
@@ -29,11 +29,13 @@ enum LunaLanguage {
ENGLISH('en', Locale('en'), 'English'),
FRENCH('fr', Locale('fr'), 'French'),
GERMAN('de', Locale('de'), 'German'),
GREEK('el', Locale('el'), 'Greek'),
HUNGARIAN('hu', Locale('hu'), 'Hungarian'),
ITALIAN('it', Locale('it'), 'Italian'),
NORWEGIAN_BOKMAL('nb-NO', Locale('nb', 'NO'), 'Norwegian (Bokmål)'),
PORTUGUESE('pt', Locale('pt'), 'Portuguese'),
RUSSIAN('ru', Locale('ru'), 'Russian'),
SLOVAK('sk', Locale('sk'), 'Slovak'),
SPANISH('es', Locale('es'), 'Spanish'),
SWEDISH('sv', Locale('sv'), 'Swedish'),
TURKISH('tr', Locale('tr'), 'Turkish'),

View File

@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:lunasea/modules/dashboard/core/state.dart' as dashboard;
import 'package:lunasea/modules/dashboard/core/state.dart';
import 'package:lunasea/modules/lidarr/core/state.dart';
import 'package:lunasea/modules/radarr/core/state.dart';
import 'package:lunasea/modules/search/core/state.dart';
@@ -12,9 +12,7 @@ import 'package:lunasea/modules/nzbget/core/state.dart';
import 'package:lunasea/modules/tautulli/core/state.dart';
import 'package:lunasea/modules.dart';
import 'package:lunasea/router/router.dart';
import 'package:provider/provider.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart' show ProviderScope;
class LunaState {
LunaState._();
@@ -27,23 +25,21 @@ class LunaState {
LunaModule.values.forEach((module) => module.state(ctx)?.reset());
}
static ProviderScope providers({required Widget child}) {
return ProviderScope(
child: MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => dashboard.ModuleState()),
ChangeNotifierProvider(create: (_) => SettingsState()),
ChangeNotifierProvider(create: (_) => SearchState()),
ChangeNotifierProvider(create: (_) => LidarrState()),
ChangeNotifierProvider(create: (_) => RadarrState()),
ChangeNotifierProvider(create: (_) => SonarrState()),
ChangeNotifierProvider(create: (_) => NZBGetState()),
ChangeNotifierProvider(create: (_) => SABnzbdState()),
ChangeNotifierProvider(create: (_) => OverseerrState()),
ChangeNotifierProvider(create: (_) => TautulliState()),
],
child: child,
),
static MultiProvider providers({required Widget child}) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => DashboardState()),
ChangeNotifierProvider(create: (_) => SettingsState()),
ChangeNotifierProvider(create: (_) => SearchState()),
ChangeNotifierProvider(create: (_) => LidarrState()),
ChangeNotifierProvider(create: (_) => RadarrState()),
ChangeNotifierProvider(create: (_) => SonarrState()),
ChangeNotifierProvider(create: (_) => NZBGetState()),
ChangeNotifierProvider(create: (_) => SABnzbdState()),
ChangeNotifierProvider(create: (_) => OverseerrState()),
ChangeNotifierProvider(create: (_) => TautulliState()),
],
child: child,
);
}
}

View File

@@ -28,7 +28,7 @@ enum LunaLogType {
bool get enabled {
switch (this) {
case LunaLogType.DEBUG:
return LunaFlavor.CANDIDATE.isRunningFlavor();
return LunaFlavor.BETA.isRunningFlavor();
default:
return true;
}

View File

@@ -1,11 +1,7 @@
import 'package:encrypt/encrypt.dart';
import 'package:lunasea/system/logger.dart';
import 'package:lunasea/vendor.dart';
class LunaEncryption {
const LunaEncryption._();
Key _generateKey(String key) {
const _length = 32;
const _pad = '0';
@@ -40,5 +36,3 @@ class LunaEncryption {
}
}
}
final encryptionProvider = Provider((_) => const LunaEncryption._());

View File

@@ -1,7 +1,7 @@
import 'package:lunasea/database/models/profile.dart';
import 'package:lunasea/database/box.dart';
import 'package:lunasea/database/tables/lunasea.dart';
import 'package:lunasea/state/state.dart';
import 'package:lunasea/system/state.dart';
import 'package:lunasea/router/router.dart';
import 'package:lunasea/system/logger.dart';
import 'package:lunasea/types/exception.dart';

View File

@@ -1,13 +1,9 @@
import 'package:lunasea/vendor.dart';
import 'package:uuid/uuid.dart';
class LunaUUID {
const LunaUUID._();
final Uuid _generator = const Uuid();
static const Uuid _generator = Uuid();
String generate() {
return _generator.v4();
}
}
final uuidProvider = Provider((_) => const LunaUUID._());

View File

@@ -1,12 +1,6 @@
import 'package:lunasea/vendor.dart';
class LunaValidator {
const LunaValidator._();
bool email(String email) {
const regex = r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)";
return RegExp(regex).hasMatch(email);
}
}
final validatorProvider = Provider((_) => const LunaValidator._());

View File

@@ -7,9 +7,7 @@ export 'dart:typed_data';
export 'package:dio/dio.dart';
export 'package:easy_localization/easy_localization.dart';
export 'package:expandable/expandable.dart';
export 'package:fading_edge_scrollview/fading_edge_scrollview.dart';
export 'package:flash/flash.dart';
export 'package:flutter_riverpod/flutter_riverpod.dart';
export 'package:go_router/go_router.dart';
export 'package:hive/hive.dart';
export 'package:hive_flutter/hive_flutter.dart';
@@ -17,7 +15,7 @@ export 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
export 'package:json_annotation/json_annotation.dart';
export 'package:meta/meta.dart';
export 'package:package_info_plus/package_info_plus.dart';
export 'package:provider/provider.dart' show ReadContext, WatchContext;
export 'package:provider/provider.dart';
export 'package:retrofit/retrofit.dart' hide Headers;
export 'package:stash/stash_api.dart';
export 'package:stash_memory/stash_memory.dart';

View File

@@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:lunasea/state/state.dart';
import 'package:lunasea/system/state.dart';
import 'package:lunasea/extensions/string/string.dart';
import 'package:lunasea/system/build.dart';
import 'package:lunasea/system/environment.dart';

View File

@@ -282,14 +282,11 @@ class _State extends State<LunaAppBar> {
mainAxisSize: MainAxisSize.min,
children: [
Flexible(
child: FadingEdgeScrollView.fromSingleChildScrollView(
child: SingleChildScrollView(
controller: ScrollController(),
scrollDirection: Axis.horizontal,
child: Text(
widget.title!,
style: const TextStyle(fontSize: LunaUI.FONT_SIZE_H1),
),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Text(
widget.title!,
style: const TextStyle(fontSize: LunaUI.FONT_SIZE_H1),
),
),
),

View File

@@ -388,12 +388,9 @@ class LunaBlock extends StatelessWidget {
required Widget child,
Axis scrollDirection = Axis.horizontal,
}) {
return FadingEdgeScrollView.fromSingleChildScrollView(
child: SingleChildScrollView(
controller: ScrollController(),
scrollDirection: scrollDirection,
child: child,
),
return SingleChildScrollView(
scrollDirection: scrollDirection,
child: child,
);
}
}

View File

@@ -138,22 +138,19 @@ class LunaGridBlock extends StatelessWidget {
Widget _title() {
return Container(
child: Padding(
child: FadingEdgeScrollView.fromSingleChildScrollView(
child: SingleChildScrollView(
controller: ScrollController(),
scrollDirection: Axis.horizontal,
child: RichText(
text: TextSpan(
style: const TextStyle(
fontSize: LunaUI.FONT_SIZE_H3,
color: LunaColours.white,
fontWeight: LunaUI.FONT_WEIGHT_BOLD,
),
text: title,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: RichText(
text: TextSpan(
style: const TextStyle(
fontSize: LunaUI.FONT_SIZE_H3,
color: LunaColours.white,
fontWeight: LunaUI.FONT_WEIGHT_BOLD,
),
overflow: TextOverflow.visible,
softWrap: false,
text: title,
),
overflow: TextOverflow.visible,
softWrap: false,
),
),
padding: LunaUI.MARGIN_DEFAULT_HORIZONTAL,
@@ -166,21 +163,19 @@ class LunaGridBlock extends StatelessWidget {
Widget _subtitle() {
return Container(
child: Padding(
child: FadingEdgeScrollView.fromSingleChildScrollView(
child: SingleChildScrollView(
controller: ScrollController(),
scrollDirection: Axis.horizontal,
child: RichText(
text: TextSpan(
style: const TextStyle(
fontSize: LunaUI.FONT_SIZE_H3,
color: LunaColours.grey,
),
children: [subtitle],
child: SingleChildScrollView(
controller: ScrollController(),
scrollDirection: Axis.horizontal,
child: RichText(
text: TextSpan(
style: const TextStyle(
fontSize: LunaUI.FONT_SIZE_H3,
color: LunaColours.grey,
),
overflow: TextOverflow.visible,
softWrap: false,
children: [subtitle],
),
overflow: TextOverflow.visible,
softWrap: false,
),
),
padding: LunaUI.MARGIN_DEFAULT_HORIZONTAL,

View File

@@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:lunasea/state/state.dart';
import 'package:lunasea/system/state.dart';
import 'package:lunasea/widgets/ui.dart';
import 'package:modal_bottom_sheet/modal_bottom_sheet.dart';

View File

@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:lunasea/state/state.dart';
import 'package:lunasea/system/state.dart';
import 'package:lunasea/types/loading_state.dart';
import 'package:lunasea/widgets/ui.dart';

View File

@@ -0,0 +1,21 @@
{
"dashboard.Friday": "Παρασκευή",
"dashboard.FutureDays": "Μελλοντικό χρόνο",
"dashboard.OneMonth": "Ένας μήνας",
"dashboard.Tuesday": "Τρίτη",
"dashboard.MinimumOfOneDay": "1 ημέρα το ελάχιστο",
"dashboard.Modules": "Ενότητες",
"dashboard.Monday": "Δευτέρα",
"dashboard.NoNewContent": "Τίποτα νέο",
"dashboard.OneWeek": "Μία εβδομάδα",
"dashboard.PastDays": "Παλαιότερες ημέρες",
"dashboard.Saturday": "Σάββατο",
"dashboard.Schedule": "Πρόγραμμα",
"dashboard.Sunday": "Κυριακή",
"dashboard.Thursday": "Πέμπτη",
"dashboard.Calendar": "Ημερολόγιο",
"dashboard.PastDaysDescription": "Τοποθετήσει τον αριθμό ημερών στο παρελθόν για εισαγωγή των εγγραφών του ημερολογίου.",
"dashboard.TwoWeeks": "Δύο εβδομάδες",
"dashboard.Wednesday": "Τετάρτη",
"dashboard.FutureDaysDescription": "Τοποθετήσει τον αριθμό ημερών στο μέλλον για εισαγωγή των εγγραφών του ημερολογίου."
}

View File

@@ -0,0 +1,21 @@
{
"dashboard.Calendar": "Kalendár",
"dashboard.Friday": "Piatok",
"dashboard.MinimumOfOneDay": "Minimálne 1 deň",
"dashboard.Modules": "Moduly",
"dashboard.Monday": "Pondelok",
"dashboard.OneMonth": "Jeden mesiac",
"dashboard.OneWeek": "Jeden týždeň",
"dashboard.PastDays": "Uplynulé dni",
"dashboard.PastDaysDescription": "Vyberte počet dní v minulosti, pre ktoré sa majú načítať záznamy z kalendára.",
"dashboard.Saturday": "Sobota",
"dashboard.Schedule": "Prehľad",
"dashboard.Sunday": "Nedeľa",
"dashboard.FutureDaysDescription": "Vyberte počet dní v budúcnosti, pre ktoré sa majú načítať záznamy z kalendára.",
"dashboard.TwoWeeks": "Dva týždne",
"dashboard.Wednesday": "Streda",
"dashboard.FutureDays": "Budúce dni",
"dashboard.Tuesday": "Utorok",
"dashboard.NoNewContent": "Žiadny nový obsah",
"dashboard.Thursday": "Štvrtok"
}

View File

@@ -0,0 +1,4 @@
{
"lidarr.StartSearchForMissingAlbums": "Ξεκίνα αναζήτηση για άλμπουμ που λείπουν",
"lidarr.StartSearchFor": "Ξεκίνα αναζήτηση…"
}

Some files were not shown because too many files have changed in this diff Show More