mirror of
https://github.com/jagandeepbrar/lunasea.git
synced 2026-08-31 04:32:32 +00:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a04fd95ed | ||
|
|
e3a21d2817 | ||
|
|
50714fa603 | ||
|
|
fe3d41af57 | ||
|
|
1304ae327d | ||
|
|
aeb80fcf08 | ||
|
|
a44ec79b3d | ||
|
|
a15d09b455 | ||
|
|
3aa2cc974c | ||
|
|
605002f5bd | ||
|
|
2f94c42da1 | ||
|
|
b65af75075 | ||
|
|
4b149b58d0 | ||
|
|
5ce12795e7 | ||
|
|
0f4ac9a893 | ||
|
|
4e243d6f30 | ||
|
|
568c28cd92 | ||
|
|
3500d83477 | ||
|
|
b515a0d14e | ||
|
|
6a2e7d83f3 | ||
|
|
f1a82c06aa | ||
|
|
c5eace4352 | ||
|
|
781727abba | ||
|
|
7c8e17e59f |
38
.github/workflows/build.yml
vendored
38
.github/workflows/build.yml
vendored
@@ -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 }}
|
||||
|
||||
6
.github/workflows/build_android.yml
vendored
6
.github/workflows/build_android.yml
vendored
@@ -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
|
||||
|
||||
6
.github/workflows/build_ios.yml
vendored
6
.github/workflows/build_ios.yml
vendored
@@ -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:
|
||||
|
||||
12
.github/workflows/build_linux.yml
vendored
12
.github/workflows/build_linux.yml
vendored
@@ -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
|
||||
|
||||
|
||||
6
.github/workflows/build_macos.yml
vendored
6
.github/workflows/build_macos.yml
vendored
@@ -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
|
||||
|
||||
2
.github/workflows/build_web.yml
vendored
2
.github/workflows/build_web.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: 'Build Web'
|
||||
name: "Build Web"
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
4
.github/workflows/build_windows.yml
vendored
4
.github/workflows/build_windows.yml
vendored
@@ -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:
|
||||
|
||||
10
.github/workflows/github_issue_labels.yml
vendored
10
.github/workflows/github_issue_labels.yml
vendored
@@ -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"
|
||||
|
||||
4
.github/workflows/notify.yml
vendored
4
.github/workflows/notify.yml
vendored
@@ -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;
|
||||
|
||||
5
.github/workflows/prepare.yml
vendored
5
.github/workflows/prepare.yml
vendored
@@ -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
|
||||
|
||||
|
||||
7
.github/workflows/publish_android.yml
vendored
7
.github/workflows/publish_android.yml
vendored
@@ -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:
|
||||
|
||||
4
.github/workflows/publish_s3.yml
vendored
4
.github/workflows/publish_s3.yml
vendored
@@ -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 }}
|
||||
|
||||
1
.github/workflows/publish_web.yml
vendored
1
.github/workflows/publish_web.yml
vendored
@@ -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';
|
||||
|
||||
22
CHANGELOG.md
22
CHANGELOG.md
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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
118
assets/localization/el.json
Normal 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"
|
||||
}
|
||||
@@ -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
132
assets/localization/sk.json
Normal 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ť!"
|
||||
}
|
||||
@@ -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",
|
||||
|
||||
@@ -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'
|
||||
|
||||
102
ios/Podfile.lock
102
ios/Podfile.lock
@@ -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
|
||||
|
||||
@@ -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 = (
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(() {});
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 = '');
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
},
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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}');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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()]),
|
||||
],
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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(),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -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();
|
||||
},
|
||||
);
|
||||
|
||||
@@ -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(),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -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],
|
||||
|
||||
@@ -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],
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -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()]),
|
||||
],
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export 'pages/ui.dart';
|
||||
@@ -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!),
|
||||
],
|
||||
),
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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(),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -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(),
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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(),
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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());
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
@@ -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),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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],
|
||||
|
||||
@@ -94,7 +94,7 @@ mixin LunaRoutesMixin on Enum {
|
||||
queryParams: queryParams,
|
||||
);
|
||||
}
|
||||
return LunaRouter.router.pushNamed(
|
||||
LunaRouter.router.pushNamed(
|
||||
_routeName,
|
||||
extra: extra,
|
||||
params: params,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
});
|
||||
@@ -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,
|
||||
);
|
||||
}
|
||||
});
|
||||
2
lib/system/cache/image/image_cache.dart
vendored
2
lib/system/cache/image/image_cache.dart
vendored
@@ -9,6 +9,6 @@ abstract class LunaImageCache {
|
||||
factory LunaImageCache() => getImageCache();
|
||||
|
||||
void initialize();
|
||||
Future<void> clear();
|
||||
Future<bool> clear();
|
||||
dynamic get instance;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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'),
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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._());
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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._());
|
||||
|
||||
@@ -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._());
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
21
localization/dashboard/el.json
Normal file
21
localization/dashboard/el.json
Normal 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": "Τοποθετήσει τον αριθμό ημερών στο μέλλον για εισαγωγή των εγγραφών του ημερολογίου."
|
||||
}
|
||||
21
localization/dashboard/sk.json
Normal file
21
localization/dashboard/sk.json
Normal 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"
|
||||
}
|
||||
4
localization/lidarr/el.json
Normal file
4
localization/lidarr/el.json
Normal 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
Reference in New Issue
Block a user