Compare commits
14 Commits
v4.12.6
...
developmen
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a179db6323 | ||
|
|
1beeab28a6 | ||
|
|
ad6a569961 | ||
|
|
0f5a8f6b97 | ||
|
|
3cd1bdf229 | ||
|
|
d7389db265 | ||
|
|
b3c93b3885 | ||
|
|
25864accc9 | ||
|
|
f734ced2cb | ||
|
|
4a3d2305c0 | ||
|
|
8db6797eaa | ||
|
|
cb4c19757d | ||
|
|
b6e75afe12 | ||
|
|
b621be06df |
22
CHANGELOG.md
@@ -1,5 +1,27 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## What's Changed
|
||||||
|
## [4.13.0](https://github.com/eddyizm/tempo/releases/tag/v4.13.0) (2026-03-25)
|
||||||
|
* chore(i18n): Improve Russian translation by @NikkoFox in https://github.com/eddyizm/tempus/pull/503
|
||||||
|
* feat: tile size manager by @MaFo-28 in https://github.com/eddyizm/tempus/pull/440
|
||||||
|
* chore(i18n): Translated to zh_TW by @olivertzeng in https://github.com/eddyizm/tempus/pull/494
|
||||||
|
* fix: Show full album name when displaying details by @jaime-grj in https://github.com/eddyizm/tempus/pull/508
|
||||||
|
* chore(i18n): Update Spanish translation by @jaime-grj in https://github.com/eddyizm/tempus/pull/509
|
||||||
|
* fix: Relocate "Offline mode" text by @jaime-grj in https://github.com/eddyizm/tempus/pull/510
|
||||||
|
* chore(i18n): Update Polish translation by @skajmer in https://github.com/eddyizm/tempus/pull/516
|
||||||
|
* refactor: navigation and bottom sheet by @tvillega in https://github.com/eddyizm/tempus/pull/491
|
||||||
|
* feat: Logo refresh by @eddyizm in https://github.com/eddyizm/tempus/pull/498
|
||||||
|
* feat: Add 'genres' page/function to Android Auto by @Jorilx in https://github.com/eddyizm/tempus/pull/505
|
||||||
|
* feat: Added all-songs feature by @unknown0816 in https://github.com/eddyizm/tempus/pull/517
|
||||||
|
|
||||||
|
## New Contributors
|
||||||
|
* @NikkoFox made their first contribution in https://github.com/eddyizm/tempus/pull/503
|
||||||
|
* @olivertzeng made their first contribution in https://github.com/eddyizm/tempus/pull/494
|
||||||
|
* @Jorilx made their first contribution in https://github.com/eddyizm/tempus/pull/505
|
||||||
|
* @unknown0816 made their first contribution in https://github.com/eddyizm/tempus/pull/517
|
||||||
|
|
||||||
|
**Full Changelog**: https://github.com/eddyizm/tempus/compare/v4.12.6...v4.13.0
|
||||||
|
|
||||||
## What's Changed
|
## What's Changed
|
||||||
## [4.12.6](https://github.com/eddyizm/tempo/releases/tag/v4.12.6) (2026-03-06)
|
## [4.12.6](https://github.com/eddyizm/tempo/releases/tag/v4.12.6) (2026-03-06)
|
||||||
* doc: update USAGE with android auto configuration by @MaFo-28 in https://github.com/eddyizm/tempus/pull/481
|
* doc: update USAGE with android auto configuration by @MaFo-28 in https://github.com/eddyizm/tempus/pull/481
|
||||||
|
|||||||
20
README.md
@@ -1,5 +1,5 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<img alt="Tempus" title="Tempus" src="mockup/svg/tempus_horizontal_logo.png" width="250">
|
<img alt="Tempus" title="Tempus" src="mockup/svg/tempus-horizontal-banner.png" width="250">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -84,13 +84,13 @@ Please note the two variants in the release assets include release/debug and 32/
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/1_light.png" width=200>
|
<img src="mockup/1_light_tempus.png" width=200>
|
||||||
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/2_light.png" width=200>
|
<img src="mockup/2_light_tempus.png" width=200>
|
||||||
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/3_light.png" width=200>
|
<img src="mockup/3_light_tempus.png" width=200>
|
||||||
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/4_light.png" width=200>
|
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/4_light.png" width=200>
|
||||||
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/5_light.png" width=200>
|
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/5_light.png" width=200>
|
||||||
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/6_light.png" width=200>
|
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/6_light.png" width=200>
|
||||||
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/8_light.png" width=200>
|
<!-- <img src="fastlane/metadata/android/en-US/images/phoneScreenshots/8_light.png" width=200> -->
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
@@ -100,13 +100,13 @@ Please note the two variants in the release assets include release/debug and 32/
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/1_dark.png" width=200>
|
<img src="mockup/1_dark_tempus.png" width=200>
|
||||||
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/2_dark.png" width=200>
|
<img src="mockup/2_dark_tempus.png" width=200>
|
||||||
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/3_dark.png" width=200>
|
<img src="mockup/3_dark_tempus.png" width=200>
|
||||||
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/4_dark.png" width=200>
|
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/4_dark.png" width=200>
|
||||||
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/5_dark.png" width=200>
|
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/5_dark.png" width=200>
|
||||||
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/6_dark.png" width=200>
|
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/6_dark.png" width=200>
|
||||||
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/8_dark.png" width=200>
|
<!-- <img src="fastlane/metadata/android/en-US/images/phoneScreenshots/8_dark.png" width=200> -->
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -136,4 +136,4 @@ Tempus is released under the [GNU General Public License v3.0](LICENSE). Feel fr
|
|||||||
## Credits
|
## Credits
|
||||||
Thanks to the original repo/creator [CappielloAntonio](https://github.com/CappielloAntonio) (forked from v3.9.0)
|
Thanks to the original repo/creator [CappielloAntonio](https://github.com/CappielloAntonio) (forked from v3.9.0)
|
||||||
|
|
||||||
[Opensvg.org](https://opensvg.org) for the new turntable logo.
|
[SeattleGuy](https://github.com/SeattleGuy) for the new logo design.
|
||||||
|
|||||||
1
USAGE.md
@@ -203,6 +203,7 @@ The Android Auto interface can be configured by user to best suit their preferen
|
|||||||
- Star albums
|
- Star albums
|
||||||
- Star artists
|
- Star artists
|
||||||
- Random : 100 random songs
|
- Random : 100 random songs
|
||||||
|
- Genres : 500 songs of the chosen genre OR 100 random songs if "shuffle genre songs" is selected
|
||||||
|
|
||||||
If all tabs are set to "Do not display", then "Home" tab will be created with all functions inside.
|
If all tabs are set to "Do not display", then "Home" tab will be created with all functions inside.
|
||||||
|
|
||||||
|
|||||||
1
_config.yml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
markdown: GFM
|
||||||
@@ -10,8 +10,8 @@ android {
|
|||||||
minSdkVersion 24
|
minSdkVersion 24
|
||||||
targetSdk 35
|
targetSdk 35
|
||||||
|
|
||||||
versionCode 23
|
versionCode 24
|
||||||
versionName '4.12.6'
|
versionName '4.13.0'
|
||||||
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
||||||
|
|
||||||
javaCompileOptions {
|
javaCompileOptions {
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 20 KiB |
10
app/src/degoogled/res/drawable/ic_launcher_background.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
|
android:viewportWidth="108"
|
||||||
|
android:viewportHeight="108">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF36C12C"
|
||||||
|
android:pathData="M0,0h108v108h-108z" />
|
||||||
|
</vector>
|
||||||
@@ -1,54 +1,78 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:aapt="http://schemas.android.com/aapt"
|
||||||
android:width="108dp"
|
android:width="108dp"
|
||||||
android:height="108dp"
|
android:height="108dp"
|
||||||
android:viewportWidth="512"
|
android:viewportWidth="108"
|
||||||
android:viewportHeight="512">
|
android:viewportHeight="108">
|
||||||
<group android:scaleX="0.49"
|
|
||||||
android:scaleY="0.49"
|
|
||||||
android:translateX="130.56"
|
|
||||||
android:translateY="130.56">
|
|
||||||
|
|
||||||
<path
|
<group
|
||||||
android:pathData="M512,437.33c0,11.78 -9.56,21.34 -21.34,21.34H21.33C9.55,458.67 0,449.11 0,437.33V96c0,-11.78 9.55,-21.33 21.33,-21.33h469.33c11.78,0 21.34,9.55 21.34,21.33L512,437.33L512,437.33z"
|
android:scaleX="0.13"
|
||||||
android:fillColor="#8CC152"/> <path
|
android:scaleY="0.13"
|
||||||
android:pathData="M512,416.01c0,11.78 -9.56,21.31 -21.34,21.31H21.33C9.55,437.33 0,427.8 0,416.01V74.67c0,-11.78 9.55,-21.34 21.33,-21.34h469.33c11.78,0 21.34,9.56 21.34,21.34L512,416.01L512,416.01z"
|
android:translateX="21.5"
|
||||||
android:fillColor="#62A43B"/> <path
|
android:translateY="21.5">
|
||||||
android:pathData="M63.99,160c-5.89,0 -10.66,4.78 -10.66,10.67v149.34c0,5.88 4.77,10.66 10.66,10.66c5.89,0 10.67,-4.78 10.67,-10.66V170.67C74.66,164.78 69.88,160 63.99,160z"
|
|
||||||
android:fillColor="#8CC152"/> <path
|
<path
|
||||||
android:pathData="M74.66,106.67c0,5.89 -4.78,10.66 -10.67,10.66c-5.89,0 -10.66,-4.77 -10.66,-10.66S58.1,96 63.99,96C69.88,96 74.66,100.78 74.66,106.67z"
|
android:pathData="M250,0c138.07,0 250,111.93 250,250S388.07,500 250,500 0,388.07 0,250 111.93,0 250,0ZM250,235c-8.28,0 -15,6.72 -15,15c0,8.28 6.72,15 15,15c8.28,0 15,-6.72 15,-15c0,-8.28 -6.72,-15 -15,-15Z">
|
||||||
android:fillColor="#E6E9ED"/>
|
<aapt:attr name="android:fillColor">
|
||||||
<path
|
<gradient
|
||||||
android:pathData="M74.66,384.01c0,5.88 -4.78,10.66 -10.67,10.66c-5.89,0 -10.66,-4.78 -10.66,-10.66c0,-5.91 4.77,-10.69 10.66,-10.69C69.88,373.33 74.66,378.11 74.66,384.01z"
|
android:startX="122.34"
|
||||||
android:fillColor="#E6E9ED"/>
|
android:startY="23.55"
|
||||||
<path
|
android:endX="377.69"
|
||||||
android:pathData="M448,123.73h-21.34v203.19l-40.31,50.41v0.02c-1.47,1.83 -2.34,4.14 -2.34,6.67c0,5.88 4.78,10.66 10.66,10.66c3.38,0 6.38,-1.56 8.33,-4h0.02l42.66,-53.34l0,0c1.47,-1.81 2.34,-4.13 2.34,-6.66V123.73z"
|
android:endY="465.83"
|
||||||
android:fillColor="#E6E9ED"/>
|
android:type="linear">
|
||||||
<path
|
<item android:offset="0.0" android:color="#FF36C12C" />
|
||||||
android:pathData="M437.33,149.33c-11.77,0 -21.33,-9.56 -21.33,-21.33s9.56,-21.33 21.33,-21.33s21.33,9.56 21.33,21.33S449.09,149.33 437.33,149.33z"
|
<item android:offset="1.0" android:color="#FF36C12C" />
|
||||||
android:fillColor="#E6E9ED"/>
|
</gradient>
|
||||||
<path
|
</aapt:attr>
|
||||||
android:pathData="M437.33,96c-17.67,0 -32,14.33 -32,32s14.33,32 32,32s32,-14.33 32,-32S455,96 437.33,96zM437.33,138.67c-5.89,0 -10.67,-4.8 -10.67,-10.67c0,-5.88 4.78,-10.67 10.67,-10.67s10.67,4.8 10.67,10.67C448,133.88 443.22,138.67 437.33,138.67z"
|
</path>
|
||||||
android:fillColor="#CCD1D9"/>
|
|
||||||
<path
|
<path
|
||||||
android:pathData="M405.33,245.33c0,82.48 -66.86,149.34 -149.33,149.34c-82.47,0 -149.33,-66.86 -149.33,-149.34C106.66,162.86 173.52,96 255.99,96C338.47,96 405.33,162.86 405.33,245.33z"
|
android:pathData="M250.41,20.5c126.89,0 229.75,102.86 229.75,229.75c0,126.89 -102.86,229.75 -229.75,229.75c-126.89,0 -229.75,-102.86 -229.75,-229.75C20.66,123.36 123.53,20.5 250.41,20.5ZM250.85,161.82c-49.09,0 -88.88,39.79 -88.88,88.88c0,49.09 39.79,88.88 88.88,88.88c49.09,0 88.88,-39.79 88.88,-88.88c0,-49.09 -39.79,-88.88 -88.88,-88.88Z">
|
||||||
android:fillColor="#434A54"/>
|
<aapt:attr name="android:fillColor">
|
||||||
<path
|
<gradient
|
||||||
android:pathData="M266.66,149.33c0,-5.89 -4.77,-10.66 -10.67,-10.66c-58.91,0 -106.66,47.75 -106.66,106.65l0,0c0,5.89 4.77,10.67 10.67,10.67s10.67,-4.78 10.67,-10.67l0,0c0,-22.78 8.88,-44.22 24.99,-60.33c16.12,-16.13 37.55,-25 60.34,-25C261.89,160 266.66,155.22 266.66,149.33z"
|
android:startX="116.21"
|
||||||
android:fillColor="#656D78"/>
|
android:startY="67.61"
|
||||||
<path
|
android:endX="403.29"
|
||||||
android:pathData="M352,234.67c-5.9,0 -10.67,4.77 -10.67,10.66l0,0c0,22.8 -8.88,44.23 -24.98,60.34c-16.13,16.13 -37.56,25 -60.35,25c-5.89,0 -10.66,4.78 -10.66,10.66c0,5.91 4.77,10.69 10.66,10.69c58.91,0 106.66,-47.77 106.66,-106.69C362.65,239.44 357.89,234.67 352,234.67z"
|
android:endY="429.34"
|
||||||
android:fillColor="#656D78"/>
|
android:type="linear">
|
||||||
<path
|
<item android:offset="0.0" android:color="#66060606" />
|
||||||
android:pathData="M255.99,288.01c-23.52,0 -42.66,-19.16 -42.66,-42.69c0,-23.52 19.14,-42.66 42.66,-42.66c23.54,0 42.66,19.14 42.66,42.66C298.65,268.86 279.53,288.01 255.99,288.01z"
|
<item android:offset="1.0" android:color="#CC060606" />
|
||||||
android:fillColor="#FFCE54"/>
|
</gradient>
|
||||||
<path
|
</aapt:attr>
|
||||||
android:pathData="M255.99,192c-29.45,0 -53.33,23.88 -53.33,53.33s23.88,53.34 53.33,53.34c29.46,0 53.34,-23.89 53.34,-53.34S285.45,192 255.99,192zM255.99,277.34c-17.64,0 -32,-14.36 -32,-32.02c0,-17.64 14.36,-32 32,-32c17.65,0 32.01,14.36 32.01,32C288,262.98 273.64,277.34 255.99,277.34z"
|
</path>
|
||||||
android:fillColor="#F6BB42"/>
|
|
||||||
<path
|
<path
|
||||||
android:pathData="M266.66,245.33c0,5.89 -4.77,10.67 -10.67,10.67c-5.89,0 -10.66,-4.78 -10.66,-10.67s4.77,-10.66 10.66,-10.66C261.89,234.67 266.66,239.44 266.66,245.33z"
|
android:pathData="M453.23,307.8c-18.5,72.24 -73.8,129.26 -144.2,148.92l-36.39,-138.74c21.97,-7.21 39.22,-24.84 45.88,-47.06l134.71,36.88Z">
|
||||||
android:fillColor="#434A54"/>
|
<aapt:attr name="android:fillColor">
|
||||||
<path
|
<gradient
|
||||||
android:pathData="M74.66,234.67H53.33c-5.89,0 -10.66,4.77 -10.66,10.66s4.77,10.67 10.66,10.67h21.34c5.89,0 10.66,-4.78 10.66,-10.67S80.56,234.67 74.66,234.67z"
|
android:startX="420.63"
|
||||||
android:fillColor="#434A54"/>
|
android:startY="403.74"
|
||||||
</group>
|
android:endX="78.4"
|
||||||
|
android:endY="117.92"
|
||||||
|
android:type="linear">
|
||||||
|
<item android:offset="0.0" android:color="#33FFFFFF" />
|
||||||
|
<item android:offset="1.0" android:color="#4DFFFFFF" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:pathData="M228.3,183.04c-21.73,7.15 -38.82,24.5 -45.62,46.39L47.5,192.42c18.5,-72.24 73.8,-129.26 144.2,-148.92l36.6,139.54Z">
|
||||||
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:startX="420.63"
|
||||||
|
android:startY="403.74"
|
||||||
|
android:endX="78.4"
|
||||||
|
android:endY="117.92"
|
||||||
|
android:type="linear">
|
||||||
|
<item android:offset="0.0" android:color="#33FFFFFF" />
|
||||||
|
<item android:offset="1.0" android:color="#4DFFFFFF" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:fillColor="#66FFFFFF"
|
||||||
|
android:pathData="M250.5,179.5c39.21,0 71,31.79 71,71s-31.79,71 -71,71s-71,-31.79 -71,-71s31.79,-71 71,-71ZM250,235c-8.28,0 -15,6.72 -15,15c0,8.28 6.72,15 15,15c8.28,0 15,-6.72 15,-15c0,-8.28 -6.72,-15 -15,-15Z" />
|
||||||
|
</group>
|
||||||
</vector>
|
</vector>
|
||||||
@@ -1,53 +1,77 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:aapt="http://schemas.android.com/aapt"
|
||||||
android:width="108dp"
|
android:width="108dp"
|
||||||
android:height="108dp"
|
android:height="108dp"
|
||||||
android:viewportWidth="512"
|
android:viewportWidth="108"
|
||||||
android:viewportHeight="512">
|
android:viewportHeight="108">
|
||||||
<group android:scaleX="0.55"
|
|
||||||
android:scaleY="0.55"
|
<group
|
||||||
android:translateX="150.56"
|
android:scaleX="0.13"
|
||||||
android:translateY="150.56">
|
android:scaleY="0.13"
|
||||||
|
android:translateX="21.5"
|
||||||
|
android:translateY="21.5">
|
||||||
<path
|
<path
|
||||||
android:pathData="M512,437.33c0,11.78 -9.56,21.34 -21.34,21.34H21.33C9.55,458.67 0,449.11 0,437.33V96c0,-11.78 9.55,-21.33 21.33,-21.33h469.33c11.78,0 21.34,9.55 21.34,21.33L512,437.33L512,437.33z"
|
android:pathData="M250,0c138.07,0 250,111.93 250,250S388.07,500 250,500 0,388.07 0,250 111.93,0 250,0ZM250,235c-8.28,0 -15,6.72 -15,15c0,8.28 6.72,15 15,15c8.28,0 15,-6.72 15,-15c0,-8.28 -6.72,-15 -15,-15Z">
|
||||||
android:fillColor="#8CC152"/> <path
|
<aapt:attr name="android:fillColor">
|
||||||
android:pathData="M512,416.01c0,11.78 -9.56,21.31 -21.34,21.31H21.33C9.55,437.33 0,427.8 0,416.01V74.67c0,-11.78 9.55,-21.34 21.33,-21.34h469.33c11.78,0 21.34,9.56 21.34,21.34L512,416.01L512,416.01z"
|
<gradient
|
||||||
android:fillColor="#62A43B"/> <path
|
android:startX="122.34"
|
||||||
android:pathData="M63.99,160c-5.89,0 -10.66,4.78 -10.66,10.67v149.34c0,5.88 4.77,10.66 10.66,10.66c5.89,0 10.67,-4.78 10.67,-10.66V170.67C74.66,164.78 69.88,160 63.99,160z"
|
android:startY="23.55"
|
||||||
android:fillColor="#8CC152"/> <path
|
android:endX="377.69"
|
||||||
android:pathData="M74.66,106.67c0,5.89 -4.78,10.66 -10.67,10.66c-5.89,0 -10.66,-4.77 -10.66,-10.66S58.1,96 63.99,96C69.88,96 74.66,100.78 74.66,106.67z"
|
android:endY="465.83"
|
||||||
android:fillColor="#E6E9ED"/>
|
android:type="linear">
|
||||||
|
<item android:offset="0.0" android:color="#FF36C12C" />
|
||||||
|
<item android:offset="1.0" android:color="#FF36C12C" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
|
||||||
<path
|
<path
|
||||||
android:pathData="M74.66,384.01c0,5.88 -4.78,10.66 -10.67,10.66c-5.89,0 -10.66,-4.78 -10.66,-10.66c0,-5.91 4.77,-10.69 10.66,-10.69C69.88,373.33 74.66,378.11 74.66,384.01z"
|
android:pathData="M250.41,20.5c126.89,0 229.75,102.86 229.75,229.75c0,126.89 -102.86,229.75 -229.75,229.75c-126.89,0 -229.75,-102.86 -229.75,-229.75C20.66,123.36 123.53,20.5 250.41,20.5ZM250.85,161.82c-49.09,0 -88.88,39.79 -88.88,88.88c0,49.09 39.79,88.88 88.88,88.88c49.09,0 88.88,-39.79 88.88,-88.88c0,-49.09 -39.79,-88.88 -88.88,-88.88Z">
|
||||||
android:fillColor="#E6E9ED"/>
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:startX="116.21"
|
||||||
|
android:startY="67.61"
|
||||||
|
android:endX="403.29"
|
||||||
|
android:endY="429.34"
|
||||||
|
android:type="linear">
|
||||||
|
<item android:offset="0.0" android:color="#66060606" />
|
||||||
|
<item android:offset="1.0" android:color="#CC060606" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
|
||||||
<path
|
<path
|
||||||
android:pathData="M448,123.73h-21.34v203.19l-40.31,50.41v0.02c-1.47,1.83 -2.34,4.14 -2.34,6.67c0,5.88 4.78,10.66 10.66,10.66c3.38,0 6.38,-1.56 8.33,-4h0.02l42.66,-53.34l0,0c1.47,-1.81 2.34,-4.13 2.34,-6.66V123.73z"
|
android:pathData="M453.23,307.8c-18.5,72.24 -73.8,129.26 -144.2,148.92l-36.39,-138.74c21.97,-7.21 39.22,-24.84 45.88,-47.06l134.71,36.88Z">
|
||||||
android:fillColor="#E6E9ED"/>
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:startX="420.63"
|
||||||
|
android:startY="403.74"
|
||||||
|
android:endX="78.4"
|
||||||
|
android:endY="117.92"
|
||||||
|
android:type="linear">
|
||||||
|
<item android:offset="0.0" android:color="#33FFFFFF" />
|
||||||
|
<item android:offset="1.0" android:color="#4DFFFFFF" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
|
||||||
<path
|
<path
|
||||||
android:pathData="M437.33,149.33c-11.77,0 -21.33,-9.56 -21.33,-21.33s9.56,-21.33 21.33,-21.33s21.33,9.56 21.33,21.33S449.09,149.33 437.33,149.33z"
|
android:pathData="M228.3,183.04c-21.73,7.15 -38.82,24.5 -45.62,46.39L47.5,192.42c18.5,-72.24 73.8,-129.26 144.2,-148.92l36.6,139.54Z">
|
||||||
android:fillColor="#E6E9ED"/>
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:startX="420.63"
|
||||||
|
android:startY="403.74"
|
||||||
|
android:endX="78.4"
|
||||||
|
android:endY="117.92"
|
||||||
|
android:type="linear">
|
||||||
|
<item android:offset="0.0" android:color="#33FFFFFF" />
|
||||||
|
<item android:offset="1.0" android:color="#4DFFFFFF" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
|
||||||
<path
|
<path
|
||||||
android:pathData="M437.33,96c-17.67,0 -32,14.33 -32,32s14.33,32 32,32s32,-14.33 32,-32S455,96 437.33,96zM437.33,138.67c-5.89,0 -10.67,-4.8 -10.67,-10.67c0,-5.88 4.78,-10.67 10.67,-10.67s10.67,4.8 10.67,10.67C448,133.88 443.22,138.67 437.33,138.67z"
|
android:fillColor="#66FFFFFF"
|
||||||
android:fillColor="#CCD1D9"/>
|
android:pathData="M250.5,179.5c39.21,0 71,31.79 71,71s-31.79,71 -71,71s-71,-31.79 -71,-71s31.79,-71 71,-71ZM250,235c-8.28,0 -15,6.72 -15,15c0,8.28 6.72,15 15,15c8.28,0 15,-6.72 15,-15c0,-8.28 -6.72,-15 -15,-15Z" />
|
||||||
<path
|
</group>
|
||||||
android:pathData="M405.33,245.33c0,82.48 -66.86,149.34 -149.33,149.34c-82.47,0 -149.33,-66.86 -149.33,-149.34C106.66,162.86 173.52,96 255.99,96C338.47,96 405.33,162.86 405.33,245.33z"
|
|
||||||
android:fillColor="#434A54"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M266.66,149.33c0,-5.89 -4.77,-10.66 -10.67,-10.66c-58.91,0 -106.66,47.75 -106.66,106.65l0,0c0,5.89 4.77,10.67 10.67,10.67s10.67,-4.78 10.67,-10.67l0,0c0,-22.78 8.88,-44.22 24.99,-60.33c16.12,-16.13 37.55,-25 60.34,-25C261.89,160 266.66,155.22 266.66,149.33z"
|
|
||||||
android:fillColor="#656D78"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M352,234.67c-5.9,0 -10.67,4.77 -10.67,10.66l0,0c0,22.8 -8.88,44.23 -24.98,60.34c-16.13,16.13 -37.56,25 -60.35,25c-5.89,0 -10.66,4.78 -10.66,10.66c0,5.91 4.77,10.69 10.66,10.69c58.91,0 106.66,-47.77 106.66,-106.69C362.65,239.44 357.89,234.67 352,234.67z"
|
|
||||||
android:fillColor="#656D78"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M255.99,288.01c-23.52,0 -42.66,-19.16 -42.66,-42.69c0,-23.52 19.14,-42.66 42.66,-42.66c23.54,0 42.66,19.14 42.66,42.66C298.65,268.86 279.53,288.01 255.99,288.01z"
|
|
||||||
android:fillColor="#FFCE54"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M255.99,192c-29.45,0 -53.33,23.88 -53.33,53.33s23.88,53.34 53.33,53.34c29.46,0 53.34,-23.89 53.34,-53.34S285.45,192 255.99,192zM255.99,277.34c-17.64,0 -32,-14.36 -32,-32.02c0,-17.64 14.36,-32 32,-32c17.65,0 32.01,14.36 32.01,32C288,262.98 273.64,277.34 255.99,277.34z"
|
|
||||||
android:fillColor="#F6BB42"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M266.66,245.33c0,5.89 -4.77,10.67 -10.67,10.67c-5.89,0 -10.66,-4.78 -10.66,-10.67s4.77,-10.66 10.66,-10.66C261.89,234.67 266.66,239.44 266.66,245.33z"
|
|
||||||
android:fillColor="#434A54"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M74.66,234.67H53.33c-5.89,0 -10.66,4.77 -10.66,10.66s4.77,10.67 10.66,10.67h21.34c5.89,0 10.66,-4.78 10.66,-10.67S80.56,234.67 74.66,234.67z"
|
|
||||||
android:fillColor="#434A54"/>
|
|
||||||
</group>
|
|
||||||
</vector>
|
</vector>
|
||||||
77
app/src/degoogled/res/drawable/ic_toolbar_tempo.xml
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:aapt="http://schemas.android.com/aapt"
|
||||||
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
|
android:viewportWidth="512"
|
||||||
|
android:viewportHeight="522">
|
||||||
|
<group
|
||||||
|
android:scaleX="1.0"
|
||||||
|
android:scaleY="1.0"
|
||||||
|
android:translateX="14.0"
|
||||||
|
android:translateY="14.0">
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:pathData="M250,0c138.07,0 250,111.93 250,250S388.07,500 250,500 0,388.07 0,250 111.93,0 250,0ZM250,235c-8.28,0 -15,6.72 -15,15c0,8.28 6.72,15 15,15c8.28,0 15,-6.72 15,-15c0,-8.28 -6.72,-15 -15,-15Z">
|
||||||
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:startX="122.34"
|
||||||
|
android:startY="23.55"
|
||||||
|
android:endX="377.69"
|
||||||
|
android:endY="465.83"
|
||||||
|
android:type="linear">
|
||||||
|
<item android:offset="0.0" android:color="#FF36C12C" />
|
||||||
|
<item android:offset="1.0" android:color="#FF36C12C" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:pathData="M250.41,20.5c126.89,0 229.75,102.86 229.75,229.75c0,126.89 -102.86,229.75 -229.75,229.75c-126.89,0 -229.75,-102.86 -229.75,-229.75C20.66,123.36 123.53,20.5 250.41,20.5ZM250.85,161.82c-49.09,0 -88.88,39.79 -88.88,88.88c0,49.09 39.79,88.88 88.88,88.88c49.09,0 88.88,-39.79 88.88,-88.88c0,-49.09 -39.79,-88.88 -88.88,-88.88Z">
|
||||||
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:startX="116.21"
|
||||||
|
android:startY="67.61"
|
||||||
|
android:endX="403.29"
|
||||||
|
android:endY="429.34"
|
||||||
|
android:type="linear">
|
||||||
|
<item android:offset="0.0" android:color="#66060606" />
|
||||||
|
<item android:offset="1.0" android:color="#CC060606" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:pathData="M453.23,307.8c-18.5,72.24 -73.8,129.26 -144.2,148.92l-36.39,-138.74c21.97,-7.21 39.22,-24.84 45.88,-47.06l134.71,36.88Z">
|
||||||
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:startX="420.63"
|
||||||
|
android:startY="403.74"
|
||||||
|
android:endX="78.4"
|
||||||
|
android:endY="117.92"
|
||||||
|
android:type="linear">
|
||||||
|
<item android:offset="0.0" android:color="#33FFFFFF" />
|
||||||
|
<item android:offset="1.0" android:color="#4DFFFFFF" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:pathData="M228.3,183.04c-21.73,7.15 -38.82,24.5 -45.62,46.39L47.5,192.42c18.5,-72.24 73.8,-129.26 144.2,-148.92l36.6,139.54Z">
|
||||||
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:startX="420.63"
|
||||||
|
android:startY="403.74"
|
||||||
|
android:endX="78.4"
|
||||||
|
android:endY="117.92"
|
||||||
|
android:type="linear">
|
||||||
|
<item android:offset="0.0" android:color="#33FFFFFF" />
|
||||||
|
<item android:offset="1.0" android:color="#4DFFFFFF" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:fillColor="#66FFFFFF"
|
||||||
|
android:pathData="M250.5,179.5c39.21,0 71,31.79 71,71s-31.79,71 -71,71s-71,-31.79 -71,-71s31.79,-71 71,-71ZM250,235c-8.28,0 -15,6.72 -15,15c0,8.28 6.72,15 15,15c8.28,0 15,-6.72 15,-15c0,-8.28 -6.72,-15 -15,-15Z" />
|
||||||
|
</group>
|
||||||
|
</vector>
|
||||||
78
app/src/degoogled/res/drawable/logo.xml
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:aapt="http://schemas.android.com/aapt"
|
||||||
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
|
android:viewportWidth="108"
|
||||||
|
android:viewportHeight="108">
|
||||||
|
|
||||||
|
<group
|
||||||
|
android:scaleX="0.16"
|
||||||
|
android:scaleY="0.16"
|
||||||
|
android:translateX="14.0"
|
||||||
|
android:translateY="14.0">
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:pathData="M250,0c138.07,0 250,111.93 250,250S388.07,500 250,500 0,388.07 0,250 111.93,0 250,0ZM250,235c-8.28,0 -15,6.72 -15,15c0,8.28 6.72,15 15,15c8.28,0 15,-6.72 15,-15c0,-8.28 -6.72,-15 -15,-15Z">
|
||||||
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:startX="122.34"
|
||||||
|
android:startY="23.55"
|
||||||
|
android:endX="377.69"
|
||||||
|
android:endY="465.83"
|
||||||
|
android:type="linear">
|
||||||
|
<item android:offset="0.0" android:color="#FF36C12C" />
|
||||||
|
<item android:offset="1.0" android:color="#FF36C12C" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:pathData="M250.41,20.5c126.89,0 229.75,102.86 229.75,229.75c0,126.89 -102.86,229.75 -229.75,229.75c-126.89,0 -229.75,-102.86 -229.75,-229.75C20.66,123.36 123.53,20.5 250.41,20.5ZM250.85,161.82c-49.09,0 -88.88,39.79 -88.88,88.88c0,49.09 39.79,88.88 88.88,88.88c49.09,0 88.88,-39.79 88.88,-88.88c0,-49.09 -39.79,-88.88 -88.88,-88.88Z">
|
||||||
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:startX="116.21"
|
||||||
|
android:startY="67.61"
|
||||||
|
android:endX="403.29"
|
||||||
|
android:endY="429.34"
|
||||||
|
android:type="linear">
|
||||||
|
<item android:offset="0.0" android:color="#66060606" />
|
||||||
|
<item android:offset="1.0" android:color="#CC060606" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:pathData="M453.23,307.8c-18.5,72.24 -73.8,129.26 -144.2,148.92l-36.39,-138.74c21.97,-7.21 39.22,-24.84 45.88,-47.06l134.71,36.88Z">
|
||||||
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:startX="420.63"
|
||||||
|
android:startY="403.74"
|
||||||
|
android:endX="78.4"
|
||||||
|
android:endY="117.92"
|
||||||
|
android:type="linear">
|
||||||
|
<item android:offset="0.0" android:color="#33FFFFFF" />
|
||||||
|
<item android:offset="1.0" android:color="#4DFFFFFF" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:pathData="M228.3,183.04c-21.73,7.15 -38.82,24.5 -45.62,46.39L47.5,192.42c18.5,-72.24 73.8,-129.26 144.2,-148.92l36.6,139.54Z">
|
||||||
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:startX="420.63"
|
||||||
|
android:startY="403.74"
|
||||||
|
android:endX="78.4"
|
||||||
|
android:endY="117.92"
|
||||||
|
android:type="linear">
|
||||||
|
<item android:offset="0.0" android:color="#33FFFFFF" />
|
||||||
|
<item android:offset="1.0" android:color="#4DFFFFFF" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:fillColor="#66FFFFFF"
|
||||||
|
android:pathData="M250.5,179.5c39.21,0 71,31.79 71,71s-31.79,71 -71,71s-71,-31.79 -71,-71s31.79,-71 71,-71ZM250,235c-8.28,0 -15,6.72 -15,15c0,8.28 6.72,15 15,15c8.28,0 15,-6.72 15,-15c0,-8.28 -6.72,-15 -15,-15Z" />
|
||||||
|
</group>
|
||||||
|
</vector>
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<background android:drawable="@color/ic_launcher_background"/>
|
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
|
<monochrome android:drawable="@drawable/ic_launcher_monochrome"/>
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<background android:drawable="@color/ic_launcher_background"/>
|
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
|
||||||
</adaptive-icon>
|
|
||||||
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 9.2 KiB |
@@ -1,4 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<color name="ic_launcher_background">#626A75</color>
|
|
||||||
</resources>
|
|
||||||
|
Before Width: | Height: | Size: 20 KiB |
@@ -0,0 +1,44 @@
|
|||||||
|
package com.cappielloantonio.tempo.navigation;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.navigation.NavController;
|
||||||
|
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
||||||
|
|
||||||
|
public class NavigationController {
|
||||||
|
|
||||||
|
NavigationHelper helper;
|
||||||
|
|
||||||
|
public NavigationController(@NonNull NavigationHelper helper) {
|
||||||
|
this.helper = helper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void syncWithBottomSheetBehavior(BottomSheetBehavior<View> bottomSheetBehavior,
|
||||||
|
NavController navController) {
|
||||||
|
helper.syncWithBottomSheetBehavior(bottomSheetBehavior, navController);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNavbarVisibility(boolean visibility) {
|
||||||
|
helper.setBottomNavigationBarVisibility(visibility);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDrawerLock(boolean visibility) {
|
||||||
|
helper.setNavigationDrawerLock(visibility);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNavigationDrawerLocked() {
|
||||||
|
return helper.isNavigationDrawerLocked();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void toggleDrawerLockOnOrientation(AppCompatActivity activity) {
|
||||||
|
helper.toggleNavigationDrawerLockOnOrientationChange(activity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSystemBarsVisibility(AppCompatActivity activity, boolean visibility) {
|
||||||
|
helper.setSystemBarsVisibility(activity, visibility);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,167 @@
|
|||||||
|
package com.cappielloantonio.tempo.navigation;
|
||||||
|
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.Window;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.OptIn;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.core.view.WindowCompat;
|
||||||
|
import androidx.core.view.WindowInsetsCompat;
|
||||||
|
import androidx.core.view.WindowInsetsControllerCompat;
|
||||||
|
import androidx.drawerlayout.widget.DrawerLayout;
|
||||||
|
import androidx.media3.common.util.UnstableApi;
|
||||||
|
import androidx.navigation.NavController;
|
||||||
|
import androidx.navigation.NavDestination;
|
||||||
|
import androidx.navigation.fragment.NavHostFragment;
|
||||||
|
import androidx.navigation.ui.NavigationUI;
|
||||||
|
|
||||||
|
import com.cappielloantonio.tempo.R;
|
||||||
|
import com.cappielloantonio.tempo.util.Preferences;
|
||||||
|
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
||||||
|
import com.google.android.material.navigation.NavigationView;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Contract;
|
||||||
|
|
||||||
|
public class NavigationHelper {
|
||||||
|
/* UI components */
|
||||||
|
private BottomNavigationView bottomNavigationView;
|
||||||
|
private FrameLayout bottomNavigationViewFrame;
|
||||||
|
private DrawerLayout drawerLayout;
|
||||||
|
|
||||||
|
/* Navigation components */
|
||||||
|
private NavigationView navigationView;
|
||||||
|
private NavHostFragment navHostFragment;
|
||||||
|
|
||||||
|
/* States that need to be remembered */
|
||||||
|
// -- //
|
||||||
|
|
||||||
|
/* Private constructor */
|
||||||
|
public NavigationHelper(@NonNull BottomNavigationView bottomNavigationView,
|
||||||
|
@NonNull FrameLayout bottomNavigationViewFrame,
|
||||||
|
@NonNull DrawerLayout drawerLayout,
|
||||||
|
@NonNull NavigationView navigationView,
|
||||||
|
@NonNull NavHostFragment navHostFragment) {
|
||||||
|
this.bottomNavigationView = bottomNavigationView;
|
||||||
|
this.bottomNavigationViewFrame = bottomNavigationViewFrame;
|
||||||
|
this.drawerLayout = drawerLayout;
|
||||||
|
this.navigationView = navigationView;
|
||||||
|
this.navHostFragment = navHostFragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void syncWithBottomSheetBehavior(@NonNull BottomSheetBehavior<View> bottomSheetBehavior,
|
||||||
|
@NonNull NavController navController) {
|
||||||
|
navController.addOnDestinationChangedListener(
|
||||||
|
(controller, destination, arguments) -> {
|
||||||
|
// React to the user clicking one of these on bottom-navbar/drawer
|
||||||
|
boolean isTarget = isTargetDestination(destination);
|
||||||
|
int currentState = bottomSheetBehavior.getState();
|
||||||
|
|
||||||
|
if (isTarget && currentState == BottomSheetBehavior.STATE_EXPANDED) {
|
||||||
|
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
NavigationUI.setupWithNavController(bottomNavigationView, navController);
|
||||||
|
NavigationUI.setupWithNavController(navigationView, navController);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Contract(pure = true)
|
||||||
|
private static boolean isTargetDestination(NavDestination destination) {
|
||||||
|
int destId = destination.getId();
|
||||||
|
return destId == R.id.homeFragment ||
|
||||||
|
destId == R.id.libraryFragment ||
|
||||||
|
destId == R.id.downloadFragment ||
|
||||||
|
destId == R.id.albumCatalogueFragment ||
|
||||||
|
destId == R.id.artistCatalogueFragment ||
|
||||||
|
destId == R.id.genreCatalogueFragment ||
|
||||||
|
destId == R.id.playlistCatalogueFragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Clean public methods
|
||||||
|
Removes the need to invoke the activity on the fragment
|
||||||
|
*/
|
||||||
|
|
||||||
|
public void setBottomNavigationBarVisibility(boolean visible) {
|
||||||
|
int visibility = visible
|
||||||
|
? View.VISIBLE
|
||||||
|
: View.GONE;
|
||||||
|
bottomNavigationView.setVisibility(visibility);
|
||||||
|
bottomNavigationViewFrame.setVisibility(visibility);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNavigationDrawerLock(boolean locked) {
|
||||||
|
int mode = locked
|
||||||
|
? DrawerLayout.LOCK_MODE_LOCKED_CLOSED
|
||||||
|
: DrawerLayout.LOCK_MODE_UNLOCKED;
|
||||||
|
drawerLayout.setDrawerLockMode(mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNavigationDrawerLocked() {
|
||||||
|
return drawerLayout.getDrawerLockMode(navigationView) != DrawerLayout.LOCK_MODE_UNLOCKED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(markerClass = UnstableApi.class)
|
||||||
|
public void toggleNavigationDrawerLockOnOrientationChange(
|
||||||
|
AppCompatActivity activity) {
|
||||||
|
|
||||||
|
int orientation = activity.getResources().getConfiguration().orientation;
|
||||||
|
boolean isLandscape = orientation == Configuration.ORIENTATION_LANDSCAPE;
|
||||||
|
|
||||||
|
if (Preferences.getEnableDrawerOnPortrait()) {
|
||||||
|
setNavigationDrawerLock(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setNavigationDrawerLock(!isLandscape);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
All of these are the "backward compatible" changes that don't break the assumption
|
||||||
|
that everything was defined on the activity and is gobally available
|
||||||
|
*/
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public BottomNavigationView getBottomNavigationView() {
|
||||||
|
return bottomNavigationView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public FrameLayout getBottomNavigationViewFrame() {
|
||||||
|
return bottomNavigationViewFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public DrawerLayout getDrawerLayout() {
|
||||||
|
return drawerLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Auxiliar functions, could be moved somewhere else
|
||||||
|
*/
|
||||||
|
|
||||||
|
@OptIn(markerClass = UnstableApi.class)
|
||||||
|
public void setSystemBarsVisibility(AppCompatActivity activity, boolean visibility) {
|
||||||
|
WindowInsetsControllerCompat insetsController;
|
||||||
|
Window window = activity.getWindow();
|
||||||
|
View decorView = window.getDecorView();
|
||||||
|
insetsController = new WindowInsetsControllerCompat(window, decorView);
|
||||||
|
|
||||||
|
if (visibility) {
|
||||||
|
WindowCompat.setDecorFitsSystemWindows(window, true);
|
||||||
|
insetsController.show(WindowInsetsCompat.Type.navigationBars());
|
||||||
|
insetsController.show(WindowInsetsCompat.Type.statusBars());
|
||||||
|
insetsController.setSystemBarsBehavior(
|
||||||
|
WindowInsetsControllerCompat.BEHAVIOR_DEFAULT);
|
||||||
|
} else {
|
||||||
|
WindowCompat.setDecorFitsSystemWindows(window, false);
|
||||||
|
insetsController.hide(WindowInsetsCompat.Type.navigationBars());
|
||||||
|
insetsController.hide(WindowInsetsCompat.Type.statusBars());
|
||||||
|
insetsController.setSystemBarsBehavior(
|
||||||
|
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -35,6 +35,7 @@ import com.cappielloantonio.tempo.subsonic.models.InternetRadioStation;
|
|||||||
import com.cappielloantonio.tempo.subsonic.models.MusicFolder;
|
import com.cappielloantonio.tempo.subsonic.models.MusicFolder;
|
||||||
import com.cappielloantonio.tempo.subsonic.models.Playlist;
|
import com.cappielloantonio.tempo.subsonic.models.Playlist;
|
||||||
import com.cappielloantonio.tempo.subsonic.models.PodcastEpisode;
|
import com.cappielloantonio.tempo.subsonic.models.PodcastEpisode;
|
||||||
|
import com.cappielloantonio.tempo.subsonic.models.Genre;
|
||||||
import com.cappielloantonio.tempo.util.DownloadUtil;
|
import com.cappielloantonio.tempo.util.DownloadUtil;
|
||||||
import com.cappielloantonio.tempo.util.MappingUtil;
|
import com.cappielloantonio.tempo.util.MappingUtil;
|
||||||
import com.cappielloantonio.tempo.util.MusicUtil;
|
import com.cappielloantonio.tempo.util.MusicUtil;
|
||||||
@@ -789,7 +790,7 @@ public class AutomotiveRepository {
|
|||||||
|
|
||||||
App.getSubsonicClientInstance(false)
|
App.getSubsonicClientInstance(false)
|
||||||
.getSearchingClient()
|
.getSearchingClient()
|
||||||
.search3(query, 20, 20, 20)
|
.search3(query, 20, 0, 20, 0, 20, 0)
|
||||||
.enqueue(new Callback<ApiResponse>() {
|
.enqueue(new Callback<ApiResponse>() {
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
|
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
|
||||||
@@ -952,6 +953,116 @@ public class AutomotiveRepository {
|
|||||||
thread.start();
|
thread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ListenableFuture<LibraryResult<ImmutableList<MediaItem>>> getGenres(String prefix) {
|
||||||
|
final SettableFuture<LibraryResult<ImmutableList<MediaItem>>> listenableFuture = SettableFuture.create();
|
||||||
|
|
||||||
|
App.getSubsonicClientInstance(false)
|
||||||
|
.getBrowsingClient()
|
||||||
|
.getGenres()
|
||||||
|
.enqueue(new Callback<ApiResponse>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
|
||||||
|
if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getGenres() != null && response.body().getSubsonicResponse().getGenres().getGenres() != null) {
|
||||||
|
List<Genre> genres = response.body().getSubsonicResponse().getGenres().getGenres();
|
||||||
|
|
||||||
|
// Sort genres alphabetically by name
|
||||||
|
genres.sort((g1, g2) -> {
|
||||||
|
String name1 = g1.getGenre() != null ? g1.getGenre() : "";
|
||||||
|
String name2 = g2.getGenre() != null ? g2.getGenre() : "";
|
||||||
|
return name1.compareToIgnoreCase(name2);
|
||||||
|
});
|
||||||
|
|
||||||
|
List<MediaItem> mediaItems = new ArrayList<>();
|
||||||
|
|
||||||
|
for (Genre genre : genres) {
|
||||||
|
MediaMetadata mediaMetadata = new MediaMetadata.Builder()
|
||||||
|
.setTitle(genre.getGenre())
|
||||||
|
.setIsBrowsable(true)
|
||||||
|
.setIsPlayable(false)
|
||||||
|
.setMediaType(MediaMetadata.MEDIA_TYPE_PLAYLIST)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
MediaItem mediaItem = new MediaItem.Builder()
|
||||||
|
.setMediaId(prefix + genre.getGenre())
|
||||||
|
.setMediaMetadata(mediaMetadata)
|
||||||
|
.setUri("")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
mediaItems.add(mediaItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
LibraryResult<ImmutableList<MediaItem>> libraryResult = LibraryResult.ofItemList(ImmutableList.copyOf(mediaItems), null);
|
||||||
|
|
||||||
|
listenableFuture.set(libraryResult);
|
||||||
|
} else {
|
||||||
|
listenableFuture.set(LibraryResult.ofError(LibraryResult.RESULT_ERROR_BAD_VALUE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
|
||||||
|
listenableFuture.setException(t);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return listenableFuture;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListenableFuture<LibraryResult<ImmutableList<MediaItem>>> getSongsByGenre(String genre, int count, boolean shuffle) {
|
||||||
|
final SettableFuture<LibraryResult<ImmutableList<MediaItem>>> listenableFuture = SettableFuture.create();
|
||||||
|
|
||||||
|
Call<ApiResponse> call;
|
||||||
|
if (shuffle) {
|
||||||
|
call = App.getSubsonicClientInstance(false)
|
||||||
|
.getAlbumSongListClient()
|
||||||
|
.getRandomSongs(count, null, null, genre);
|
||||||
|
} else {
|
||||||
|
call = App.getSubsonicClientInstance(false)
|
||||||
|
.getAlbumSongListClient()
|
||||||
|
.getSongsByGenre(genre, count, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
call.enqueue(new Callback<ApiResponse>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
|
||||||
|
if (response.isSuccessful() && response.body() != null) {
|
||||||
|
List<com.cappielloantonio.tempo.subsonic.models.Child> songs;
|
||||||
|
if (shuffle) {
|
||||||
|
songs = response.body().getSubsonicResponse().getRandomSongs() != null
|
||||||
|
? response.body().getSubsonicResponse().getRandomSongs().getSongs()
|
||||||
|
: null;
|
||||||
|
} else {
|
||||||
|
songs = response.body().getSubsonicResponse().getSongsByGenre() != null
|
||||||
|
? response.body().getSubsonicResponse().getSongsByGenre().getSongs()
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (songs != null) {
|
||||||
|
setChildrenMetadata(songs);
|
||||||
|
List<MediaItem> mediaItems = MappingUtil.mapMediaItems(songs);
|
||||||
|
LibraryResult<ImmutableList<MediaItem>> libraryResult = LibraryResult.ofItemList(ImmutableList.copyOf(mediaItems), null);
|
||||||
|
listenableFuture.set(libraryResult);
|
||||||
|
} else {
|
||||||
|
listenableFuture.set(LibraryResult.ofError(LibraryResult.RESULT_ERROR_BAD_VALUE));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
listenableFuture.set(LibraryResult.ofError(LibraryResult.RESULT_ERROR_BAD_VALUE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
|
||||||
|
listenableFuture.setException(t);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return listenableFuture;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListenableFuture<LibraryResult<ImmutableList<MediaItem>>> getSongsByGenre(String genre, int count) {
|
||||||
|
return getSongsByGenre(genre, count, false);
|
||||||
|
}
|
||||||
|
|
||||||
private static class GetMediaItemThreadSafe implements Runnable {
|
private static class GetMediaItemThreadSafe implements Runnable {
|
||||||
private final SessionMediaItemDao sessionMediaItemDao;
|
private final SessionMediaItemDao sessionMediaItemDao;
|
||||||
private final String id;
|
private final String id;
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
package com.cappielloantonio.tempo.repository;
|
package com.cappielloantonio.tempo.repository;
|
||||||
|
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.lifecycle.MutableLiveData;
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
import androidx.media3.common.util.UnstableApi;
|
||||||
|
|
||||||
import com.cappielloantonio.tempo.App;
|
import com.cappielloantonio.tempo.App;
|
||||||
|
import com.cappielloantonio.tempo.R;
|
||||||
import com.cappielloantonio.tempo.database.AppDatabase;
|
import com.cappielloantonio.tempo.database.AppDatabase;
|
||||||
import com.cappielloantonio.tempo.database.dao.RecentSearchDao;
|
import com.cappielloantonio.tempo.database.dao.RecentSearchDao;
|
||||||
import com.cappielloantonio.tempo.model.RecentSearch;
|
import com.cappielloantonio.tempo.model.RecentSearch;
|
||||||
@@ -11,13 +16,18 @@ import com.cappielloantonio.tempo.subsonic.base.ApiResponse;
|
|||||||
import com.cappielloantonio.tempo.subsonic.models.AlbumID3;
|
import com.cappielloantonio.tempo.subsonic.models.AlbumID3;
|
||||||
import com.cappielloantonio.tempo.subsonic.models.ArtistID3;
|
import com.cappielloantonio.tempo.subsonic.models.ArtistID3;
|
||||||
import com.cappielloantonio.tempo.subsonic.models.Child;
|
import com.cappielloantonio.tempo.subsonic.models.Child;
|
||||||
|
import com.cappielloantonio.tempo.subsonic.models.Playlist;
|
||||||
|
import com.cappielloantonio.tempo.subsonic.models.PlaylistWithSongs;
|
||||||
import com.cappielloantonio.tempo.subsonic.models.SearchResult2;
|
import com.cappielloantonio.tempo.subsonic.models.SearchResult2;
|
||||||
import com.cappielloantonio.tempo.subsonic.models.SearchResult3;
|
import com.cappielloantonio.tempo.subsonic.models.SearchResult3;
|
||||||
import com.cappielloantonio.tempo.util.Preferences;
|
import com.cappielloantonio.tempo.util.Preferences;
|
||||||
|
import com.cappielloantonio.tempo.ui.fragment.SearchFragment;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
import retrofit2.Call;
|
import retrofit2.Call;
|
||||||
import retrofit2.Callback;
|
import retrofit2.Callback;
|
||||||
@@ -31,7 +41,7 @@ public class SearchingRepository {
|
|||||||
|
|
||||||
App.getSubsonicClientInstance(false)
|
App.getSubsonicClientInstance(false)
|
||||||
.getSearchingClient()
|
.getSearchingClient()
|
||||||
.search3(query, 20, 20, 20)
|
.search3(query, 20, 0, 20, 0, 20, 0)
|
||||||
.enqueue(new Callback<ApiResponse>() {
|
.enqueue(new Callback<ApiResponse>() {
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
|
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
|
||||||
@@ -49,12 +59,63 @@ public class SearchingRepository {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MutableLiveData<SearchResult3> search3(String query) {
|
@UnstableApi
|
||||||
|
public MutableLiveData<SearchResult3> search3(SearchFragment sf, String query) {
|
||||||
MutableLiveData<SearchResult3> result = new MutableLiveData<>();
|
MutableLiveData<SearchResult3> result = new MutableLiveData<>();
|
||||||
|
|
||||||
|
Executors.newSingleThreadExecutor().execute(() -> {
|
||||||
|
List<Child> allSongs = new ArrayList<>();
|
||||||
|
int offset = 0;
|
||||||
|
int limit = 1000;
|
||||||
|
boolean hasMore = true;
|
||||||
|
|
||||||
|
while (hasMore) {
|
||||||
|
try {
|
||||||
|
Response<ApiResponse> response = App.getSubsonicClientInstance(false)
|
||||||
|
.getSearchingClient()
|
||||||
|
.search3(query, limit, offset, 0, 0, 0, 0)
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
if (response.isSuccessful() && response.body() != null) {
|
||||||
|
SearchResult3 tmp = response.body().getSubsonicResponse().getSearchResult3();
|
||||||
|
if (tmp != null && tmp.getSongs() != null && !tmp.getSongs().isEmpty()) {
|
||||||
|
List<Child> fetchedSongs = tmp.getSongs();
|
||||||
|
allSongs.addAll(fetchedSongs);
|
||||||
|
|
||||||
|
offset += fetchedSongs.size();
|
||||||
|
hasMore = fetchedSongs.size() == limit;
|
||||||
|
} else {
|
||||||
|
hasMore = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hasMore = false;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
hasMore = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PlaylistWithSongs pws = new PlaylistWithSongs("allsongs", allSongs);
|
||||||
|
pws.setName(sf.getView().getContext().getString(R.string.search_all_songs, String.valueOf(allSongs.size())));
|
||||||
|
pws.setSongCount(allSongs.size());
|
||||||
|
List<Playlist> lpws = new ArrayList<>();
|
||||||
|
lpws.add(pws);
|
||||||
|
long duration = 0;
|
||||||
|
for (Child song: allSongs) {
|
||||||
|
if (song != null && song.getDuration() != null) {
|
||||||
|
duration += song.getDuration();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pws.setDuration(duration);
|
||||||
|
|
||||||
|
new Handler(Looper.getMainLooper()).post(() -> {
|
||||||
|
sf.updateUI(lpws);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
App.getSubsonicClientInstance(false)
|
App.getSubsonicClientInstance(false)
|
||||||
.getSearchingClient()
|
.getSearchingClient()
|
||||||
.search3(query, 20, 20, 20)
|
.search3(query, 20, 0, 20, 0, 20, 0)
|
||||||
.enqueue(new Callback<ApiResponse>() {
|
.enqueue(new Callback<ApiResponse>() {
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
|
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
|
||||||
@@ -77,7 +138,7 @@ public class SearchingRepository {
|
|||||||
|
|
||||||
App.getSubsonicClientInstance(false)
|
App.getSubsonicClientInstance(false)
|
||||||
.getSearchingClient()
|
.getSearchingClient()
|
||||||
.search3(query, 5, 5, 5)
|
.search3(query, 5, 0, 5, 0, 5, 0)
|
||||||
.enqueue(new Callback<ApiResponse>() {
|
.enqueue(new Callback<ApiResponse>() {
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
|
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ public class SearchingClient {
|
|||||||
return searchingService.search2(subsonic.getParams(), query, songCount, albumCount, artistCount);
|
return searchingService.search2(subsonic.getParams(), query, songCount, albumCount, artistCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Call<ApiResponse> search3(String query, int songCount, int albumCount, int artistCount) {
|
public Call<ApiResponse> search3(String query, int songCount, int songOffset, int albumCount, int albumOffset, int artistCount, int artistOffset) {
|
||||||
Log.d(TAG, "search3()");
|
Log.d(TAG, "search3()");
|
||||||
return searchingService.search3(subsonic.getParams(), query, songCount, albumCount, artistCount);
|
return searchingService.search3(subsonic.getParams(), query, songCount, songOffset, albumCount, albumOffset, artistCount, artistOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,5 +14,5 @@ public interface SearchingService {
|
|||||||
Call<ApiResponse> search2(@QueryMap Map<String, String> params, @Query("query") String query, @Query("songCount") int songCount, @Query("albumCount") int albumCount, @Query("artistCount") int artistCount);
|
Call<ApiResponse> search2(@QueryMap Map<String, String> params, @Query("query") String query, @Query("songCount") int songCount, @Query("albumCount") int albumCount, @Query("artistCount") int artistCount);
|
||||||
|
|
||||||
@GET("search3")
|
@GET("search3")
|
||||||
Call<ApiResponse> search3(@QueryMap Map<String, String> params, @Query("query") String query, @Query("songCount") int songCount, @Query("albumCount") int albumCount, @Query("artistCount") int artistCount);
|
Call<ApiResponse> search3(@QueryMap Map<String, String> params, @Query("query") String query, @Query("songCount") int songCount, @Query("songOffset") int songOffset, @Query("albumCount") int albumCount, @Query("albumOffset") int albumOffset, @Query("artistCount") int artistCount, @Query("artistOffset") int artistOffset);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,23 +4,16 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.graphics.Rect;
|
|
||||||
import android.content.IntentFilter;
|
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.NetworkInfo;
|
import android.net.NetworkInfo;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.Gravity;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.core.splashscreen.SplashScreen;
|
import androidx.core.splashscreen.SplashScreen;
|
||||||
import androidx.core.view.WindowCompat;
|
|
||||||
import androidx.core.view.WindowInsetsCompat;
|
|
||||||
import androidx.core.view.WindowInsetsControllerCompat;
|
|
||||||
import androidx.drawerlayout.widget.DrawerLayout;
|
import androidx.drawerlayout.widget.DrawerLayout;
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
@@ -31,7 +24,6 @@ import androidx.media3.common.Player;
|
|||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
import androidx.navigation.NavController;
|
import androidx.navigation.NavController;
|
||||||
import androidx.navigation.fragment.NavHostFragment;
|
import androidx.navigation.fragment.NavHostFragment;
|
||||||
import androidx.navigation.ui.NavigationUI;
|
|
||||||
|
|
||||||
import com.cappielloantonio.tempo.App;
|
import com.cappielloantonio.tempo.App;
|
||||||
import com.cappielloantonio.tempo.BuildConfig;
|
import com.cappielloantonio.tempo.BuildConfig;
|
||||||
@@ -39,8 +31,12 @@ import com.cappielloantonio.tempo.R;
|
|||||||
import com.cappielloantonio.tempo.broadcast.receiver.ConnectivityStatusBroadcastReceiver;
|
import com.cappielloantonio.tempo.broadcast.receiver.ConnectivityStatusBroadcastReceiver;
|
||||||
import com.cappielloantonio.tempo.databinding.ActivityMainBinding;
|
import com.cappielloantonio.tempo.databinding.ActivityMainBinding;
|
||||||
import com.cappielloantonio.tempo.github.utils.UpdateUtil;
|
import com.cappielloantonio.tempo.github.utils.UpdateUtil;
|
||||||
|
import com.cappielloantonio.tempo.navigation.NavigationController;
|
||||||
|
import com.cappielloantonio.tempo.navigation.NavigationHelper;
|
||||||
import com.cappielloantonio.tempo.service.MediaManager;
|
import com.cappielloantonio.tempo.service.MediaManager;
|
||||||
import com.cappielloantonio.tempo.ui.activity.base.BaseActivity;
|
import com.cappielloantonio.tempo.ui.activity.base.BaseActivity;
|
||||||
|
import com.cappielloantonio.tempo.ui.controller.BottomSheetController;
|
||||||
|
import com.cappielloantonio.tempo.ui.controller.BottomSheetHelper;
|
||||||
import com.cappielloantonio.tempo.ui.dialog.ConnectionAlertDialog;
|
import com.cappielloantonio.tempo.ui.dialog.ConnectionAlertDialog;
|
||||||
import com.cappielloantonio.tempo.ui.dialog.GithubTempoUpdateDialog;
|
import com.cappielloantonio.tempo.ui.dialog.GithubTempoUpdateDialog;
|
||||||
import com.cappielloantonio.tempo.ui.dialog.ServerUnreachableDialog;
|
import com.cappielloantonio.tempo.ui.dialog.ServerUnreachableDialog;
|
||||||
@@ -70,10 +66,12 @@ public class MainActivity extends BaseActivity {
|
|||||||
private NavHostFragment navHostFragment;
|
private NavHostFragment navHostFragment;
|
||||||
private BottomNavigationView bottomNavigationView;
|
private BottomNavigationView bottomNavigationView;
|
||||||
private FrameLayout bottomNavigationViewFrame;
|
private FrameLayout bottomNavigationViewFrame;
|
||||||
public NavController navController;
|
|
||||||
private DrawerLayout drawerLayout;
|
private DrawerLayout drawerLayout;
|
||||||
private NavigationView navigationView;
|
private NavigationView navigationView;
|
||||||
private BottomSheetBehavior bottomSheetBehavior;
|
public NavController navController;
|
||||||
|
private NavigationController navigationController;
|
||||||
|
private BottomSheetController bottomSheetController;
|
||||||
|
public BottomSheetBehavior bottomSheetBehavior;
|
||||||
public boolean isLandscape = false;
|
public boolean isLandscape = false;
|
||||||
private AssetLinkNavigator assetLinkNavigator;
|
private AssetLinkNavigator assetLinkNavigator;
|
||||||
private AssetLinkUtil.AssetLink pendingAssetLink;
|
private AssetLinkUtil.AssetLink pendingAssetLink;
|
||||||
@@ -81,6 +79,10 @@ public class MainActivity extends BaseActivity {
|
|||||||
ConnectivityStatusBroadcastReceiver connectivityStatusBroadcastReceiver;
|
ConnectivityStatusBroadcastReceiver connectivityStatusBroadcastReceiver;
|
||||||
private Intent pendingDownloadPlaybackIntent;
|
private Intent pendingDownloadPlaybackIntent;
|
||||||
|
|
||||||
|
public ActivityMainBinding getBinding() {
|
||||||
|
return bind;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
SplashScreen.installSplashScreen(this);
|
SplashScreen.installSplashScreen(this);
|
||||||
@@ -147,7 +149,6 @@ public class MainActivity extends BaseActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void init() {
|
public void init() {
|
||||||
fragmentManager = getSupportFragmentManager();
|
|
||||||
|
|
||||||
initBottomSheet();
|
initBottomSheet();
|
||||||
initNavigation();
|
initNavigation();
|
||||||
@@ -162,49 +163,74 @@ public class MainActivity extends BaseActivity {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BOTTOM SHEET/NAVIGATION
|
private void initNavigation() {
|
||||||
private void initBottomSheet() {
|
// We link the nav_graph.xml with our navigationController
|
||||||
bottomSheetBehavior = BottomSheetBehavior.from(findViewById(R.id.player_bottom_sheet));
|
NavHostFragment navHostFragment = (NavHostFragment) this
|
||||||
bottomSheetBehavior.addBottomSheetCallback(bottomSheetCallback);
|
.getSupportFragmentManager()
|
||||||
fragmentManager.beginTransaction().replace(R.id.player_bottom_sheet, new PlayerBottomSheetFragment(), "PlayerBottomSheet").commit();
|
.findFragmentById(R.id.nav_host_fragment);
|
||||||
|
navController = Objects.requireNonNull(navHostFragment).getNavController();
|
||||||
|
/*
|
||||||
|
navController is currently global since some legacy code still invokes it directly
|
||||||
|
the MainActivity methods that use it must be converted to NavigationHelper methods
|
||||||
|
*/
|
||||||
|
|
||||||
checkBottomSheetAfterStateChanged();
|
// Helper
|
||||||
|
NavigationHelper navigationHelper =
|
||||||
|
new NavigationHelper(
|
||||||
|
findViewById(R.id.bottom_navigation),
|
||||||
|
findViewById(R.id.bottom_navigation_frame),
|
||||||
|
findViewById(R.id.drawer_layout),
|
||||||
|
findViewById(R.id.nav_view),
|
||||||
|
navHostFragment
|
||||||
|
);
|
||||||
|
|
||||||
|
// Controller
|
||||||
|
navigationController = new NavigationController(navigationHelper);
|
||||||
|
navigationController.syncWithBottomSheetBehavior(bottomSheetBehavior, navController);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initBottomSheet() {
|
||||||
|
FragmentManager fragmentManager = getSupportFragmentManager();
|
||||||
|
View bottomSheetView = findViewById(R.id.player_bottom_sheet);
|
||||||
|
bottomSheetBehavior = BottomSheetBehavior.from(bottomSheetView);
|
||||||
|
/*
|
||||||
|
bottomSheetBehavior is currently global since some legacy code still invokes it directly
|
||||||
|
the MainActivity methods that use it must be converted to BottomSheetHelper methods
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Helper
|
||||||
|
BottomSheetHelper bottomSheetHelper =
|
||||||
|
new BottomSheetHelper(
|
||||||
|
bottomSheetBehavior,
|
||||||
|
bottomSheetView,
|
||||||
|
fragmentManager
|
||||||
|
);
|
||||||
|
|
||||||
|
// Controller
|
||||||
|
bottomSheetController = new BottomSheetController(bottomSheetHelper);
|
||||||
|
bottomSheetController.addCallback(bottomSheetCallback);
|
||||||
|
bottomSheetController.replaceFragment(R.id.player_bottom_sheet);
|
||||||
|
bottomSheetController.checkAfterStateChanged(mainViewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBottomSheetInPeek(Boolean isVisible) {
|
public void setBottomSheetInPeek(Boolean isVisible) {
|
||||||
if (isVisible) {
|
bottomSheetController.setStateInPeek(isVisible);
|
||||||
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
|
|
||||||
} else {
|
|
||||||
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBottomSheetVisibility(boolean visibility) {
|
public void setBottomSheetVisibility(boolean visibility) {
|
||||||
if (visibility) {
|
bottomSheetController.setVisibility(visibility);
|
||||||
findViewById(R.id.player_bottom_sheet).setVisibility(View.VISIBLE);
|
|
||||||
} else {
|
|
||||||
findViewById(R.id.player_bottom_sheet).setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkBottomSheetAfterStateChanged() {
|
|
||||||
final Handler handler = new Handler();
|
|
||||||
final Runnable runnable = () -> setBottomSheetInPeek(mainViewModel.isQueueLoaded());
|
|
||||||
handler.postDelayed(runnable, 100);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void collapseBottomSheetDelayed() {
|
public void collapseBottomSheetDelayed() {
|
||||||
final Handler handler = new Handler();
|
bottomSheetController.collapseDelayed();
|
||||||
final Runnable runnable = () -> bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
|
|
||||||
handler.postDelayed(runnable, 100);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void expandBottomSheet() {
|
public void expandBottomSheet() {
|
||||||
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
|
bottomSheetController.expand();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBottomSheetDraggableState(Boolean isDraggable) {
|
public void setBottomSheetDraggableState(Boolean isDraggable) {
|
||||||
bottomSheetBehavior.setDraggable(isDraggable);
|
bottomSheetController.setDraggable(isDraggable);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final BottomSheetBehavior.BottomSheetCallback bottomSheetCallback =
|
private final BottomSheetBehavior.BottomSheetCallback bottomSheetCallback =
|
||||||
@@ -217,7 +243,7 @@ public class MainActivity extends BaseActivity {
|
|||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case BottomSheetBehavior.STATE_HIDDEN:
|
case BottomSheetBehavior.STATE_HIDDEN:
|
||||||
resetMusicSession();
|
resetMusicSession(); // I can't put the callback inside BottomSheetHelper because of this line
|
||||||
break;
|
break;
|
||||||
case BottomSheetBehavior.STATE_COLLAPSED:
|
case BottomSheetBehavior.STATE_COLLAPSED:
|
||||||
if (playerBottomSheetFragment != null)
|
if (playerBottomSheetFragment != null)
|
||||||
@@ -241,12 +267,7 @@ public class MainActivity extends BaseActivity {
|
|||||||
};
|
};
|
||||||
|
|
||||||
private void animateBottomSheet(float slideOffset) {
|
private void animateBottomSheet(float slideOffset) {
|
||||||
PlayerBottomSheetFragment playerBottomSheetFragment = (PlayerBottomSheetFragment) getSupportFragmentManager().findFragmentByTag("PlayerBottomSheet");
|
bottomSheetController.animate(slideOffset);
|
||||||
if (playerBottomSheetFragment != null) {
|
|
||||||
float condensedSlideOffset = Math.max(0.0f, Math.min(0.2f, slideOffset - 0.2f)) / 0.2f;
|
|
||||||
playerBottomSheetFragment.getPlayerHeader().setAlpha(1 - condensedSlideOffset);
|
|
||||||
playerBottomSheetFragment.getPlayerHeader().setVisibility(condensedSlideOffset > 0.99 ? View.GONE : View.VISIBLE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void animateBottomNavigation(float slideOffset, int navigationHeight) {
|
private void animateBottomNavigation(float slideOffset, int navigationHeight) {
|
||||||
@@ -261,117 +282,56 @@ public class MainActivity extends BaseActivity {
|
|||||||
bind.bottomNavigation.setTranslationY(slideY);
|
bind.bottomNavigation.setTranslationY(slideY);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initNavigation() {
|
|
||||||
bottomNavigationView = findViewById(R.id.bottom_navigation);
|
|
||||||
bottomNavigationViewFrame = findViewById(R.id.bottom_navigation_frame);
|
|
||||||
navHostFragment = (NavHostFragment) fragmentManager.findFragmentById(R.id.nav_host_fragment);
|
|
||||||
navController = Objects.requireNonNull(navHostFragment).getNavController();
|
|
||||||
// This is the lateral slide-in drawer
|
|
||||||
drawerLayout = findViewById(R.id.drawer_layout);
|
|
||||||
navigationView = findViewById(R.id.nav_view);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* In questo modo intercetto il cambio schermata tramite navbar e se il bottom sheet è aperto,
|
|
||||||
* lo chiudo
|
|
||||||
*/
|
|
||||||
navController.addOnDestinationChangedListener((controller, destination, arguments) -> {
|
|
||||||
if (bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED && (
|
|
||||||
destination.getId() == R.id.homeFragment ||
|
|
||||||
destination.getId() == R.id.libraryFragment ||
|
|
||||||
destination.getId() == R.id.downloadFragment ||
|
|
||||||
destination.getId() == R.id.albumCatalogueFragment ||
|
|
||||||
destination.getId() == R.id.artistCatalogueFragment ||
|
|
||||||
destination.getId() == R.id.genreCatalogueFragment ||
|
|
||||||
destination.getId() == R.id.playlistCatalogueFragment)
|
|
||||||
) {
|
|
||||||
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
NavigationUI.setupWithNavController(bottomNavigationView, navController);
|
|
||||||
NavigationUI.setupWithNavController(navigationView, navController);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBottomNavigationBarVisibility(boolean visibility) {
|
public void setBottomNavigationBarVisibility(boolean visibility) {
|
||||||
if (visibility) {
|
navigationController.setNavbarVisibility(visibility);
|
||||||
bottomNavigationView.setVisibility(View.VISIBLE);
|
|
||||||
bottomNavigationViewFrame.setVisibility(View.VISIBLE);
|
|
||||||
} else {
|
|
||||||
bottomNavigationView.setVisibility(View.GONE);
|
|
||||||
bottomNavigationViewFrame.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void toggleBottomNavigationBarVisibilityOnOrientationChange() {
|
public void toggleBottomNavigationBarVisibilityOnOrientationChange() {
|
||||||
|
float displayDensity = getResources().getDisplayMetrics().density;
|
||||||
// Ignore orientation change, bottom navbar always hidden
|
// Ignore orientation change, bottom navbar always hidden
|
||||||
if (Preferences.getHideBottomNavbarOnPortrait()) {
|
if (Preferences.getHideBottomNavbarOnPortrait()) {
|
||||||
setBottomNavigationBarVisibility(false);
|
navigationController.setNavbarVisibility(false);
|
||||||
setPortraitPlayerBottomSheetPeekHeight(56);
|
bottomSheetController.setPeekHeight(56, displayDensity);
|
||||||
setSystemBarsVisibility(!isLandscape);
|
navigationController.setSystemBarsVisibility(this, !isLandscape);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isLandscape) {
|
if (!isLandscape) {
|
||||||
// Show app navbar + show system bars
|
// Show app navbar + show system bars
|
||||||
setPortraitPlayerBottomSheetPeekHeight(136);
|
bottomSheetController.setPeekHeight(136, displayDensity);
|
||||||
setBottomNavigationBarVisibility(true);
|
navigationController.setNavbarVisibility(true);
|
||||||
setSystemBarsVisibility(true);
|
navigationController.setSystemBarsVisibility(this, true);
|
||||||
} else {
|
} else {
|
||||||
// Hide app navbar + hide system bars
|
// Hide app navbar + hide system bars
|
||||||
setPortraitPlayerBottomSheetPeekHeight(56);
|
bottomSheetController.setPeekHeight(56, displayDensity);
|
||||||
setBottomNavigationBarVisibility(false);
|
navigationController.setNavbarVisibility(false);
|
||||||
setSystemBarsVisibility(false);
|
navigationController.setSystemBarsVisibility(this, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNavigationDrawerLock(boolean locked) {
|
public void setNavigationDrawerLock(boolean locked) {
|
||||||
int mode = locked
|
navigationController.setDrawerLock(locked);
|
||||||
? DrawerLayout.LOCK_MODE_LOCKED_CLOSED
|
}
|
||||||
: DrawerLayout.LOCK_MODE_UNLOCKED;
|
|
||||||
drawerLayout.setDrawerLockMode(mode);
|
public boolean isNavigationDrawerLocked() {
|
||||||
|
return navigationController.isNavigationDrawerLocked();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void toggleNavigationDrawerLockOnOrientationChange() {
|
public void toggleNavigationDrawerLockOnOrientationChange() {
|
||||||
// Ignore orientation check, drawer always unlocked
|
navigationController.toggleDrawerLockOnOrientation(this);
|
||||||
if (Preferences.getEnableDrawerOnPortrait()) {
|
|
||||||
setNavigationDrawerLock(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!isLandscape) {
|
|
||||||
setNavigationDrawerLock(true);
|
|
||||||
} else {
|
|
||||||
setNavigationDrawerLock(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSystemBarsVisibility(boolean visibility) {
|
public void setSystemBarsVisibility(boolean visibility) {
|
||||||
WindowInsetsControllerCompat insetsController;
|
navigationController.setSystemBarsVisibility(this, visibility);
|
||||||
View decorView = getWindow().getDecorView();
|
|
||||||
insetsController = new WindowInsetsControllerCompat(getWindow(), decorView);
|
|
||||||
|
|
||||||
if (visibility) {
|
|
||||||
WindowCompat.setDecorFitsSystemWindows(getWindow(), true);
|
|
||||||
insetsController.show(WindowInsetsCompat.Type.navigationBars());
|
|
||||||
insetsController.show(WindowInsetsCompat.Type.statusBars());
|
|
||||||
insetsController.setSystemBarsBehavior(
|
|
||||||
WindowInsetsControllerCompat.BEHAVIOR_DEFAULT);
|
|
||||||
} else {
|
|
||||||
WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
|
|
||||||
insetsController.hide(WindowInsetsCompat.Type.navigationBars());
|
|
||||||
insetsController.hide(WindowInsetsCompat.Type.statusBars());
|
|
||||||
insetsController.setSystemBarsBehavior(
|
|
||||||
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setPortraitPlayerBottomSheetPeekHeight(int peekHeight) {
|
/*
|
||||||
FrameLayout bottomSheet = findViewById(R.id.player_bottom_sheet);
|
There are only 4 init functions that must exist up to here
|
||||||
BottomSheetBehavior<FrameLayout> behavior =
|
1. init()
|
||||||
BottomSheetBehavior.from(bottomSheet);
|
2. initNavigation()
|
||||||
|
3. initBottomSheet()
|
||||||
int newPeekPx = (int) (peekHeight * getResources().getDisplayMetrics().density);
|
4. bottomSheetCallback = new BottomSheetBehavior.BottomSheetCallback() { ... }
|
||||||
behavior.setPeekHeight(newPeekPx);
|
*/
|
||||||
}
|
|
||||||
|
|
||||||
private void initService() {
|
private void initService() {
|
||||||
MediaManager.check(getMediaBrowserListenableFuture());
|
MediaManager.check(getMediaBrowserListenableFuture());
|
||||||
@@ -407,7 +367,7 @@ public class MainActivity extends BaseActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void goToHome() {
|
private void goToHome() {
|
||||||
bottomNavigationView.setVisibility(View.VISIBLE);
|
setBottomNavigationBarVisibility(true);
|
||||||
|
|
||||||
if (Objects.requireNonNull(navController.getCurrentDestination()).getId() == R.id.landingFragment) {
|
if (Objects.requireNonNull(navController.getCurrentDestination()).getId() == R.id.landingFragment) {
|
||||||
navController.navigate(R.id.action_landingFragment_to_homeFragment);
|
navController.navigate(R.id.action_landingFragment_to_homeFragment);
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import com.cappielloantonio.tempo.interfaces.ClickCallback;
|
|||||||
import com.cappielloantonio.tempo.subsonic.models.AlbumID3;
|
import com.cappielloantonio.tempo.subsonic.models.AlbumID3;
|
||||||
import com.cappielloantonio.tempo.util.Constants;
|
import com.cappielloantonio.tempo.util.Constants;
|
||||||
import com.cappielloantonio.tempo.util.MusicUtil;
|
import com.cappielloantonio.tempo.util.MusicUtil;
|
||||||
|
import com.cappielloantonio.tempo.util.TileSizeManager;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -22,6 +23,8 @@ public class AlbumAdapter extends RecyclerView.Adapter<AlbumAdapter.ViewHolder>
|
|||||||
|
|
||||||
private List<AlbumID3> albums;
|
private List<AlbumID3> albums;
|
||||||
|
|
||||||
|
private int sizePx = 400;
|
||||||
|
|
||||||
public AlbumAdapter(ClickCallback click) {
|
public AlbumAdapter(ClickCallback click) {
|
||||||
this.click = click;
|
this.click = click;
|
||||||
this.albums = Collections.emptyList();
|
this.albums = Collections.emptyList();
|
||||||
@@ -31,11 +34,20 @@ public class AlbumAdapter extends RecyclerView.Adapter<AlbumAdapter.ViewHolder>
|
|||||||
@Override
|
@Override
|
||||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
ItemLibraryAlbumBinding view = ItemLibraryAlbumBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
ItemLibraryAlbumBinding view = ItemLibraryAlbumBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
||||||
|
|
||||||
|
TileSizeManager.getInstance().calculateTileSize(parent.getContext());
|
||||||
|
sizePx = TileSizeManager.getInstance().getTileSizePx(parent.getContext());
|
||||||
|
|
||||||
return new ViewHolder(view);
|
return new ViewHolder(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||||
|
ViewGroup.LayoutParams lp = holder.item.albumCoverImageView.getLayoutParams();
|
||||||
|
lp.width = sizePx;
|
||||||
|
lp.height = sizePx;
|
||||||
|
holder.item.albumCoverImageView.setLayoutParams(lp);
|
||||||
|
|
||||||
AlbumID3 album = albums.get(position);
|
AlbumID3 album = albums.get(position);
|
||||||
|
|
||||||
holder.item.albumNameLabel.setText(album.getName());
|
holder.item.albumNameLabel.setText(album.getName());
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import com.cappielloantonio.tempo.interfaces.ClickCallback;
|
|||||||
import com.cappielloantonio.tempo.subsonic.models.ArtistID3;
|
import com.cappielloantonio.tempo.subsonic.models.ArtistID3;
|
||||||
import com.cappielloantonio.tempo.util.Constants;
|
import com.cappielloantonio.tempo.util.Constants;
|
||||||
import com.cappielloantonio.tempo.util.MusicUtil;
|
import com.cappielloantonio.tempo.util.MusicUtil;
|
||||||
|
import com.cappielloantonio.tempo.util.TileSizeManager;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -24,6 +25,7 @@ public class ArtistAdapter extends RecyclerView.Adapter<ArtistAdapter.ViewHolder
|
|||||||
private final boolean mix;
|
private final boolean mix;
|
||||||
private final boolean bestOf;
|
private final boolean bestOf;
|
||||||
|
|
||||||
|
private int sizePx = 400;
|
||||||
private List<ArtistID3> artists;
|
private List<ArtistID3> artists;
|
||||||
|
|
||||||
public ArtistAdapter(ClickCallback click, Boolean mix, Boolean bestOf) {
|
public ArtistAdapter(ClickCallback click, Boolean mix, Boolean bestOf) {
|
||||||
@@ -37,11 +39,20 @@ public class ArtistAdapter extends RecyclerView.Adapter<ArtistAdapter.ViewHolder
|
|||||||
@Override
|
@Override
|
||||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
ItemLibraryArtistBinding view = ItemLibraryArtistBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
ItemLibraryArtistBinding view = ItemLibraryArtistBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
||||||
|
|
||||||
|
TileSizeManager.getInstance().calculateTileSize(parent.getContext());
|
||||||
|
sizePx = TileSizeManager.getInstance().getTileSizePx(parent.getContext());
|
||||||
|
|
||||||
return new ViewHolder(view);
|
return new ViewHolder(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||||
|
ViewGroup.LayoutParams lp = holder.item.artistCoverImageView.getLayoutParams();
|
||||||
|
lp.width = sizePx;
|
||||||
|
lp.height = sizePx;
|
||||||
|
holder.item.artistCoverImageView.setLayoutParams(lp);
|
||||||
|
|
||||||
ArtistID3 artist = artists.get(position);
|
ArtistID3 artist = artists.get(position);
|
||||||
|
|
||||||
holder.item.artistNameLabel.setText(artist.getName());
|
holder.item.artistNameLabel.setText(artist.getName());
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import com.cappielloantonio.tempo.interfaces.ClickCallback;
|
|||||||
import com.cappielloantonio.tempo.subsonic.models.SimilarArtistID3;
|
import com.cappielloantonio.tempo.subsonic.models.SimilarArtistID3;
|
||||||
import com.cappielloantonio.tempo.util.Constants;
|
import com.cappielloantonio.tempo.util.Constants;
|
||||||
import com.cappielloantonio.tempo.util.MusicUtil;
|
import com.cappielloantonio.tempo.util.MusicUtil;
|
||||||
|
import com.cappielloantonio.tempo.util.TileSizeManager;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -22,6 +23,8 @@ public class ArtistSimilarAdapter extends RecyclerView.Adapter<ArtistSimilarAdap
|
|||||||
|
|
||||||
private List<SimilarArtistID3> artists;
|
private List<SimilarArtistID3> artists;
|
||||||
|
|
||||||
|
private int sizePx = 400;
|
||||||
|
|
||||||
public ArtistSimilarAdapter(ClickCallback click) {
|
public ArtistSimilarAdapter(ClickCallback click) {
|
||||||
this.click = click;
|
this.click = click;
|
||||||
this.artists = Collections.emptyList();
|
this.artists = Collections.emptyList();
|
||||||
@@ -31,11 +34,20 @@ public class ArtistSimilarAdapter extends RecyclerView.Adapter<ArtistSimilarAdap
|
|||||||
@Override
|
@Override
|
||||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
ItemLibrarySimilarArtistBinding view = ItemLibrarySimilarArtistBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
ItemLibrarySimilarArtistBinding view = ItemLibrarySimilarArtistBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
||||||
|
|
||||||
|
TileSizeManager.getInstance().calculateTileSize(parent.getContext());
|
||||||
|
sizePx = TileSizeManager.getInstance().getTileSizePx(parent.getContext());
|
||||||
|
|
||||||
return new ViewHolder(view);
|
return new ViewHolder(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||||
|
ViewGroup.LayoutParams lp = holder.item.similarArtistCoverImageView.getLayoutParams();
|
||||||
|
lp.width = sizePx;
|
||||||
|
lp.height = sizePx;
|
||||||
|
holder.item.similarArtistCoverImageView.setLayoutParams(lp);
|
||||||
|
|
||||||
SimilarArtistID3 artist = artists.get(position);
|
SimilarArtistID3 artist = artists.get(position);
|
||||||
|
|
||||||
holder.item.artistNameLabel.setText(artist.getName());
|
holder.item.artistNameLabel.setText(artist.getName());
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.cappielloantonio.tempo.ui.adapter;
|
|||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||||
|
|
||||||
@@ -14,6 +15,7 @@ import com.cappielloantonio.tempo.interfaces.ClickCallback;
|
|||||||
import com.cappielloantonio.tempo.subsonic.models.Child;
|
import com.cappielloantonio.tempo.subsonic.models.Child;
|
||||||
import com.cappielloantonio.tempo.util.Constants;
|
import com.cappielloantonio.tempo.util.Constants;
|
||||||
import com.cappielloantonio.tempo.util.MusicUtil;
|
import com.cappielloantonio.tempo.util.MusicUtil;
|
||||||
|
import com.cappielloantonio.tempo.util.TileSizeManager;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -23,6 +25,9 @@ public class DiscoverSongAdapter extends RecyclerView.Adapter<DiscoverSongAdapte
|
|||||||
|
|
||||||
private List<Child> songs;
|
private List<Child> songs;
|
||||||
|
|
||||||
|
private int widthPx = 800;
|
||||||
|
private int heightPx = 400;
|
||||||
|
|
||||||
public DiscoverSongAdapter(ClickCallback click) {
|
public DiscoverSongAdapter(ClickCallback click) {
|
||||||
this.click = click;
|
this.click = click;
|
||||||
this.songs = Collections.emptyList();
|
this.songs = Collections.emptyList();
|
||||||
@@ -32,11 +37,21 @@ public class DiscoverSongAdapter extends RecyclerView.Adapter<DiscoverSongAdapte
|
|||||||
@Override
|
@Override
|
||||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
ItemHomeDiscoverSongBinding view = ItemHomeDiscoverSongBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
ItemHomeDiscoverSongBinding view = ItemHomeDiscoverSongBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
||||||
|
|
||||||
|
TileSizeManager.getInstance().calculateDiscoverSize(parent.getContext());
|
||||||
|
widthPx = TileSizeManager.getInstance().getDiscoverWidthPx(parent.getContext());;
|
||||||
|
heightPx = TileSizeManager.getInstance().getDiscoverHeightPx(parent.getContext());;
|
||||||
|
|
||||||
return new ViewHolder(view);
|
return new ViewHolder(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||||
|
ViewGroup.LayoutParams lp = holder.item.discoverSongCoverImageView.getLayoutParams();
|
||||||
|
lp.width = widthPx;
|
||||||
|
lp.height = heightPx;
|
||||||
|
holder.item.discoverSongCoverImageView.setLayoutParams(lp);
|
||||||
|
|
||||||
Child song = songs.get(position);
|
Child song = songs.get(position);
|
||||||
|
|
||||||
holder.item.titleDiscoverSongLabel.setText(song.getTitle());
|
holder.item.titleDiscoverSongLabel.setText(song.getTitle());
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package com.cappielloantonio.tempo.ui.controller;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.cappielloantonio.tempo.viewmodel.MainViewModel;
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
||||||
|
|
||||||
|
public class BottomSheetController {
|
||||||
|
|
||||||
|
BottomSheetHelper helper;
|
||||||
|
|
||||||
|
public BottomSheetController(@NonNull BottomSheetHelper bottomSheetPlayerHelper) {
|
||||||
|
this.helper = bottomSheetPlayerHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void expand() {
|
||||||
|
helper.setState(BottomSheetBehavior.STATE_EXPANDED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void hide() {
|
||||||
|
helper.setState(BottomSheetBehavior.STATE_HIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStateInPeek(boolean isVisible) {
|
||||||
|
helper.setStateInPeek(isVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVisibility(boolean visibility) {
|
||||||
|
helper.setVisibility(visibility);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addCallback(BottomSheetBehavior.BottomSheetCallback callback) {
|
||||||
|
helper.addCallback(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void replaceFragment(int playerBottomSheet) {
|
||||||
|
helper.replaceFragment(playerBottomSheet);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkAfterStateChanged(MainViewModel mainViewModel) {
|
||||||
|
helper.checkAfterStateChanged(mainViewModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void collapseDelayed() {
|
||||||
|
helper.collapseDelayed();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDraggable(Boolean isDraggable) {
|
||||||
|
helper.setDraggable(isDraggable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getState() {
|
||||||
|
return helper.getState();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void animate(float slideOffset) {
|
||||||
|
helper.animate(slideOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPeekHeight(int peekHeight, float displayDensity) {
|
||||||
|
helper.setPeekHeight(peekHeight, displayDensity);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
package com.cappielloantonio.tempo.ui.controller;
|
||||||
|
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
|
||||||
|
import com.cappielloantonio.tempo.R;
|
||||||
|
import com.cappielloantonio.tempo.ui.fragment.PlayerBottomSheetFragment;
|
||||||
|
import com.cappielloantonio.tempo.viewmodel.MainViewModel;
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
||||||
|
|
||||||
|
public class BottomSheetHelper {
|
||||||
|
|
||||||
|
BottomSheetBehavior<View> bottomSheetBehavior;
|
||||||
|
View bottomSheetView;
|
||||||
|
FragmentManager fragmentManager; // Of the entire activity
|
||||||
|
PlayerBottomSheetFragment playerBottomSheetFragment;
|
||||||
|
|
||||||
|
public void setState(int state) {
|
||||||
|
bottomSheetBehavior.setState(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BottomSheetHelper(@NonNull BottomSheetBehavior<View> bottomSheetBehavior,
|
||||||
|
@NonNull View bottomSheetView,
|
||||||
|
@NonNull FragmentManager fragmentManager) {
|
||||||
|
this.bottomSheetBehavior = bottomSheetBehavior;
|
||||||
|
this.bottomSheetView = bottomSheetView;
|
||||||
|
this.fragmentManager = fragmentManager;
|
||||||
|
this.playerBottomSheetFragment = new PlayerBottomSheetFragment();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addCallback(BottomSheetBehavior.BottomSheetCallback callback) {
|
||||||
|
bottomSheetBehavior.addBottomSheetCallback(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStateInPeek(boolean isVisible) {
|
||||||
|
if (isVisible) {
|
||||||
|
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
|
||||||
|
} else {
|
||||||
|
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVisibility(boolean visibility) {
|
||||||
|
if (visibility) {
|
||||||
|
bottomSheetView.setVisibility(View.VISIBLE);
|
||||||
|
} else {
|
||||||
|
bottomSheetView.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void replaceFragment(int playerBottomSheet) {
|
||||||
|
fragmentManager
|
||||||
|
.beginTransaction()
|
||||||
|
.replace(
|
||||||
|
playerBottomSheet,
|
||||||
|
playerBottomSheetFragment,
|
||||||
|
"PlayerBottomSheet")
|
||||||
|
.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkAfterStateChanged(MainViewModel mainViewModel) {
|
||||||
|
final Handler handler = new Handler();
|
||||||
|
final Runnable runnable = () -> setStateInPeek(mainViewModel.isQueueLoaded());
|
||||||
|
handler.postDelayed(runnable, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void collapseDelayed() {
|
||||||
|
final Handler handler = new Handler();
|
||||||
|
final Runnable runnable = () -> bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
|
||||||
|
handler.postDelayed(runnable, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDraggable(Boolean isDraggable) {
|
||||||
|
bottomSheetBehavior.setDraggable((isDraggable));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getState() {
|
||||||
|
return bottomSheetBehavior.getState();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void animate(float slideOffset) {
|
||||||
|
if (playerBottomSheetFragment != null) {
|
||||||
|
float condensedSlideOffset = Math.max(0.0f, Math.min(0.2f, slideOffset - 0.2f)) / 0.2f;
|
||||||
|
playerBottomSheetFragment.getPlayerHeader().setAlpha(1 - condensedSlideOffset);
|
||||||
|
playerBottomSheetFragment.getPlayerHeader().setVisibility(condensedSlideOffset > 0.99 ? View.GONE : View.VISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPeekHeight(int peekHeight, float displayDensity) {
|
||||||
|
int newPeekPx = (int) (peekHeight * displayDensity);
|
||||||
|
bottomSheetBehavior.setPeekHeight(newPeekPx);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -35,6 +35,7 @@ import com.cappielloantonio.tempo.ui.activity.MainActivity;
|
|||||||
import com.cappielloantonio.tempo.ui.adapter.AlbumCatalogueAdapter;
|
import com.cappielloantonio.tempo.ui.adapter.AlbumCatalogueAdapter;
|
||||||
import com.cappielloantonio.tempo.util.Constants;
|
import com.cappielloantonio.tempo.util.Constants;
|
||||||
import com.cappielloantonio.tempo.util.Preferences;
|
import com.cappielloantonio.tempo.util.Preferences;
|
||||||
|
import com.cappielloantonio.tempo.util.TileSizeManager;
|
||||||
import com.cappielloantonio.tempo.viewmodel.AlbumCatalogueViewModel;
|
import com.cappielloantonio.tempo.viewmodel.AlbumCatalogueViewModel;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -48,9 +49,9 @@ public class AlbumCatalogueFragment extends Fragment implements ClickCallback {
|
|||||||
private FragmentAlbumCatalogueBinding bind;
|
private FragmentAlbumCatalogueBinding bind;
|
||||||
private MainActivity activity;
|
private MainActivity activity;
|
||||||
private AlbumCatalogueViewModel albumCatalogueViewModel;
|
private AlbumCatalogueViewModel albumCatalogueViewModel;
|
||||||
|
|
||||||
private AlbumCatalogueAdapter albumAdapter;
|
|
||||||
private int spanCount = 2;
|
private int spanCount = 2;
|
||||||
|
private int tileSpacing = 20;
|
||||||
|
private AlbumCatalogueAdapter albumAdapter;
|
||||||
private String currentSortOrder;
|
private String currentSortOrder;
|
||||||
private List<com.cappielloantonio.tempo.subsonic.models.AlbumID3> originalAlbums;
|
private List<com.cappielloantonio.tempo.subsonic.models.AlbumID3> originalAlbums;
|
||||||
|
|
||||||
@@ -92,9 +93,9 @@ public class AlbumCatalogueFragment extends Fragment implements ClickCallback {
|
|||||||
bind = FragmentAlbumCatalogueBinding.inflate(inflater, container, false);
|
bind = FragmentAlbumCatalogueBinding.inflate(inflater, container, false);
|
||||||
View view = bind.getRoot();
|
View view = bind.getRoot();
|
||||||
|
|
||||||
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
TileSizeManager.getInstance().calculateTileSize( requireContext() );
|
||||||
spanCount = Preferences.getLandscapeItemsPerRow();
|
spanCount = TileSizeManager.getInstance().getTileSpanCount( requireContext() );
|
||||||
}
|
tileSpacing = TileSizeManager.getInstance().getTileSpacing( requireContext() );
|
||||||
|
|
||||||
initAppBar();
|
initAppBar();
|
||||||
initAlbumCatalogueView();
|
initAlbumCatalogueView();
|
||||||
@@ -140,7 +141,7 @@ public class AlbumCatalogueFragment extends Fragment implements ClickCallback {
|
|||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
private void initAlbumCatalogueView() {
|
private void initAlbumCatalogueView() {
|
||||||
bind.albumCatalogueRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), spanCount));
|
bind.albumCatalogueRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), spanCount));
|
||||||
bind.albumCatalogueRecyclerView.addItemDecoration(new GridItemDecoration(spanCount, 20, false));
|
bind.albumCatalogueRecyclerView.addItemDecoration(new GridItemDecoration(spanCount, tileSpacing, false));
|
||||||
bind.albumCatalogueRecyclerView.setHasFixedSize(true);
|
bind.albumCatalogueRecyclerView.setHasFixedSize(true);
|
||||||
|
|
||||||
albumAdapter = new AlbumCatalogueAdapter(this, true);
|
albumAdapter = new AlbumCatalogueAdapter(this, true);
|
||||||
|
|||||||
@@ -261,8 +261,10 @@ public class AlbumPageFragment extends Fragment implements ClickCallback {
|
|||||||
bind.albumOtherInfoButton.setOnClickListener(v -> {
|
bind.albumOtherInfoButton.setOnClickListener(v -> {
|
||||||
if (bind.albumDetailView.getVisibility() == View.GONE) {
|
if (bind.albumDetailView.getVisibility() == View.GONE) {
|
||||||
bind.albumDetailView.setVisibility(View.VISIBLE);
|
bind.albumDetailView.setVisibility(View.VISIBLE);
|
||||||
|
bind.albumNameLabel.setMaxLines(Integer.MAX_VALUE);
|
||||||
} else if (bind.albumDetailView.getVisibility() == View.VISIBLE) {
|
} else if (bind.albumDetailView.getVisibility() == View.VISIBLE) {
|
||||||
bind.albumDetailView.setVisibility(View.GONE);
|
bind.albumDetailView.setVisibility(View.GONE);
|
||||||
|
bind.albumNameLabel.setMaxLines(2);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import com.cappielloantonio.tempo.ui.activity.MainActivity;
|
|||||||
import com.cappielloantonio.tempo.ui.adapter.ArtistCatalogueAdapter;
|
import com.cappielloantonio.tempo.ui.adapter.ArtistCatalogueAdapter;
|
||||||
import com.cappielloantonio.tempo.util.Constants;
|
import com.cappielloantonio.tempo.util.Constants;
|
||||||
import com.cappielloantonio.tempo.util.Preferences;
|
import com.cappielloantonio.tempo.util.Preferences;
|
||||||
|
import com.cappielloantonio.tempo.util.TileSizeManager;
|
||||||
import com.cappielloantonio.tempo.viewmodel.ArtistCatalogueViewModel;
|
import com.cappielloantonio.tempo.viewmodel.ArtistCatalogueViewModel;
|
||||||
import com.cappielloantonio.tempo.subsonic.models.ArtistID3;
|
import com.cappielloantonio.tempo.subsonic.models.ArtistID3;
|
||||||
|
|
||||||
@@ -51,7 +52,9 @@ public class ArtistCatalogueFragment extends Fragment implements ClickCallback {
|
|||||||
private ArtistCatalogueViewModel artistCatalogueViewModel;
|
private ArtistCatalogueViewModel artistCatalogueViewModel;
|
||||||
|
|
||||||
private ArtistCatalogueAdapter artistAdapter;
|
private ArtistCatalogueAdapter artistAdapter;
|
||||||
|
|
||||||
private int spanCount = 2;
|
private int spanCount = 2;
|
||||||
|
private int tileSpacing = 20;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
@@ -68,9 +71,9 @@ public class ArtistCatalogueFragment extends Fragment implements ClickCallback {
|
|||||||
bind = FragmentArtistCatalogueBinding.inflate(inflater, container, false);
|
bind = FragmentArtistCatalogueBinding.inflate(inflater, container, false);
|
||||||
View view = bind.getRoot();
|
View view = bind.getRoot();
|
||||||
|
|
||||||
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
TileSizeManager.getInstance().calculateTileSize( requireContext() );
|
||||||
spanCount = Preferences.getLandscapeItemsPerRow();
|
spanCount = TileSizeManager.getInstance().getTileSpanCount( requireContext() );
|
||||||
}
|
tileSpacing = TileSizeManager.getInstance().getTileSpacing( requireContext() );
|
||||||
|
|
||||||
initAppBar();
|
initAppBar();
|
||||||
initArtistCatalogueView();
|
initArtistCatalogueView();
|
||||||
@@ -115,7 +118,7 @@ public class ArtistCatalogueFragment extends Fragment implements ClickCallback {
|
|||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
private void initArtistCatalogueView() {
|
private void initArtistCatalogueView() {
|
||||||
bind.artistCatalogueRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), spanCount));
|
bind.artistCatalogueRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), spanCount));
|
||||||
bind.artistCatalogueRecyclerView.addItemDecoration(new GridItemDecoration(spanCount, 20, false));
|
bind.artistCatalogueRecyclerView.addItemDecoration(new GridItemDecoration(spanCount, tileSpacing, false));
|
||||||
bind.artistCatalogueRecyclerView.setHasFixedSize(true);
|
bind.artistCatalogueRecyclerView.setHasFixedSize(true);
|
||||||
|
|
||||||
artistAdapter = new ArtistCatalogueAdapter(this);
|
artistAdapter = new ArtistCatalogueAdapter(this);
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ import com.cappielloantonio.tempo.ui.adapter.SongHorizontalAdapter;
|
|||||||
import com.cappielloantonio.tempo.util.Constants;
|
import com.cappielloantonio.tempo.util.Constants;
|
||||||
import com.cappielloantonio.tempo.util.MusicUtil;
|
import com.cappielloantonio.tempo.util.MusicUtil;
|
||||||
import com.cappielloantonio.tempo.util.Preferences;
|
import com.cappielloantonio.tempo.util.Preferences;
|
||||||
|
import com.cappielloantonio.tempo.util.TileSizeManager;
|
||||||
import com.cappielloantonio.tempo.viewmodel.ArtistPageViewModel;
|
import com.cappielloantonio.tempo.viewmodel.ArtistPageViewModel;
|
||||||
import com.cappielloantonio.tempo.viewmodel.PlaybackViewModel;
|
import com.cappielloantonio.tempo.viewmodel.PlaybackViewModel;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
@@ -65,6 +66,7 @@ public class ArtistPageFragment extends Fragment implements ClickCallback {
|
|||||||
private ListenableFuture<MediaBrowser> mediaBrowserListenableFuture;
|
private ListenableFuture<MediaBrowser> mediaBrowserListenableFuture;
|
||||||
|
|
||||||
private int spanCount = 2;
|
private int spanCount = 2;
|
||||||
|
private int tileSpacing = 20;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
@@ -75,9 +77,9 @@ public class ArtistPageFragment extends Fragment implements ClickCallback {
|
|||||||
artistPageViewModel = new ViewModelProvider(requireActivity()).get(ArtistPageViewModel.class);
|
artistPageViewModel = new ViewModelProvider(requireActivity()).get(ArtistPageViewModel.class);
|
||||||
playbackViewModel = new ViewModelProvider(requireActivity()).get(PlaybackViewModel.class);
|
playbackViewModel = new ViewModelProvider(requireActivity()).get(PlaybackViewModel.class);
|
||||||
|
|
||||||
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
TileSizeManager.getInstance().calculateTileSize( requireContext() );
|
||||||
spanCount = Preferences.getLandscapeItemsPerRow();
|
spanCount = TileSizeManager.getInstance().getTileSpanCount( requireContext() );
|
||||||
}
|
tileSpacing = TileSizeManager.getInstance().getTileSpacing( requireContext() );
|
||||||
|
|
||||||
init(view);
|
init(view);
|
||||||
initAppBar();
|
initAppBar();
|
||||||
@@ -285,7 +287,7 @@ public class ArtistPageFragment extends Fragment implements ClickCallback {
|
|||||||
|
|
||||||
private void initAlbumsView() {
|
private void initAlbumsView() {
|
||||||
bind.albumsRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), spanCount));
|
bind.albumsRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), spanCount));
|
||||||
bind.albumsRecyclerView.addItemDecoration(new GridItemDecoration(spanCount, 20, false));
|
bind.albumsRecyclerView.addItemDecoration(new GridItemDecoration(spanCount, tileSpacing, false));
|
||||||
bind.albumsRecyclerView.setHasFixedSize(true);
|
bind.albumsRecyclerView.setHasFixedSize(true);
|
||||||
|
|
||||||
albumCatalogueAdapter = new AlbumCatalogueAdapter(this, false);
|
albumCatalogueAdapter = new AlbumCatalogueAdapter(this, false);
|
||||||
@@ -304,7 +306,7 @@ public class ArtistPageFragment extends Fragment implements ClickCallback {
|
|||||||
|
|
||||||
private void initSimilarArtistsView() {
|
private void initSimilarArtistsView() {
|
||||||
bind.similarArtistsRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), spanCount));
|
bind.similarArtistsRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), spanCount));
|
||||||
bind.similarArtistsRecyclerView.addItemDecoration(new GridItemDecoration(spanCount, 20, false));
|
bind.similarArtistsRecyclerView.addItemDecoration(new GridItemDecoration(spanCount, tileSpacing, false));
|
||||||
bind.similarArtistsRecyclerView.setHasFixedSize(true);
|
bind.similarArtistsRecyclerView.setHasFixedSize(true);
|
||||||
|
|
||||||
artistCatalogueAdapter = new ArtistCatalogueAdapter(this);
|
artistCatalogueAdapter = new ArtistCatalogueAdapter(this);
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import com.cappielloantonio.tempo.ui.activity.MainActivity;
|
|||||||
import com.cappielloantonio.tempo.ui.adapter.GenreCatalogueAdapter;
|
import com.cappielloantonio.tempo.ui.adapter.GenreCatalogueAdapter;
|
||||||
import com.cappielloantonio.tempo.util.Constants;
|
import com.cappielloantonio.tempo.util.Constants;
|
||||||
import com.cappielloantonio.tempo.util.Preferences;
|
import com.cappielloantonio.tempo.util.Preferences;
|
||||||
|
import com.cappielloantonio.tempo.util.TileSizeManager;
|
||||||
import com.cappielloantonio.tempo.viewmodel.GenreCatalogueViewModel;
|
import com.cappielloantonio.tempo.viewmodel.GenreCatalogueViewModel;
|
||||||
|
|
||||||
@OptIn(markerClass = UnstableApi.class)
|
@OptIn(markerClass = UnstableApi.class)
|
||||||
@@ -43,7 +44,9 @@ public class GenreCatalogueFragment extends Fragment implements ClickCallback {
|
|||||||
private GenreCatalogueViewModel genreCatalogueViewModel;
|
private GenreCatalogueViewModel genreCatalogueViewModel;
|
||||||
|
|
||||||
private GenreCatalogueAdapter genreCatalogueAdapter;
|
private GenreCatalogueAdapter genreCatalogueAdapter;
|
||||||
|
|
||||||
private int spanCount = 2;
|
private int spanCount = 2;
|
||||||
|
private int tileSpacing = 20;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
@@ -59,9 +62,9 @@ public class GenreCatalogueFragment extends Fragment implements ClickCallback {
|
|||||||
View view = bind.getRoot();
|
View view = bind.getRoot();
|
||||||
genreCatalogueViewModel = new ViewModelProvider(requireActivity()).get(GenreCatalogueViewModel.class);
|
genreCatalogueViewModel = new ViewModelProvider(requireActivity()).get(GenreCatalogueViewModel.class);
|
||||||
|
|
||||||
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
TileSizeManager.getInstance().calculateGenreSize( requireContext() );
|
||||||
spanCount = Preferences.getLandscapeItemsPerRow();
|
spanCount = TileSizeManager.getInstance().getGenreSpanCount( requireContext() );
|
||||||
}
|
tileSpacing = TileSizeManager.getInstance().getGenreSpacing( requireContext() );
|
||||||
|
|
||||||
init();
|
init();
|
||||||
initAppBar();
|
initAppBar();
|
||||||
@@ -105,7 +108,7 @@ public class GenreCatalogueFragment extends Fragment implements ClickCallback {
|
|||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
private void initGenreCatalogueView() {
|
private void initGenreCatalogueView() {
|
||||||
bind.genreCatalogueRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), spanCount));
|
bind.genreCatalogueRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), spanCount));
|
||||||
bind.genreCatalogueRecyclerView.addItemDecoration(new GridItemDecoration(spanCount, 16, false));
|
bind.genreCatalogueRecyclerView.addItemDecoration(new GridItemDecoration(spanCount, tileSpacing, false));
|
||||||
bind.genreCatalogueRecyclerView.setHasFixedSize(true);
|
bind.genreCatalogueRecyclerView.setHasFixedSize(true);
|
||||||
|
|
||||||
genreCatalogueAdapter = new GenreCatalogueAdapter(this);
|
genreCatalogueAdapter = new GenreCatalogueAdapter(this);
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ import com.cappielloantonio.tempo.util.ExternalAudioWriter;
|
|||||||
import com.cappielloantonio.tempo.util.MappingUtil;
|
import com.cappielloantonio.tempo.util.MappingUtil;
|
||||||
import com.cappielloantonio.tempo.util.MusicUtil;
|
import com.cappielloantonio.tempo.util.MusicUtil;
|
||||||
import com.cappielloantonio.tempo.util.Preferences;
|
import com.cappielloantonio.tempo.util.Preferences;
|
||||||
|
import com.cappielloantonio.tempo.util.TileSizeManager;
|
||||||
import com.cappielloantonio.tempo.util.UIUtil;
|
import com.cappielloantonio.tempo.util.UIUtil;
|
||||||
import com.cappielloantonio.tempo.viewmodel.HomeViewModel;
|
import com.cappielloantonio.tempo.viewmodel.HomeViewModel;
|
||||||
import com.cappielloantonio.tempo.viewmodel.PlaybackViewModel;
|
import com.cappielloantonio.tempo.viewmodel.PlaybackViewModel;
|
||||||
@@ -682,11 +683,12 @@ public class HomeTabMusicFragment extends Fragment implements ClickCallback {
|
|||||||
private void initDiscoverSongSlideView() {
|
private void initDiscoverSongSlideView() {
|
||||||
if (homeViewModel.checkHomeSectorVisibility(Constants.HOME_SECTOR_DISCOVERY)) return;
|
if (homeViewModel.checkHomeSectorVisibility(Constants.HOME_SECTOR_DISCOVERY)) return;
|
||||||
|
|
||||||
bind.discoverSongViewPager.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
|
bind.discoverSongRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false));
|
||||||
|
bind.discoverSongRecyclerView.setHasFixedSize(true);
|
||||||
|
|
||||||
discoverSongAdapter = new DiscoverSongAdapter(this);
|
discoverSongAdapter = new DiscoverSongAdapter(this);
|
||||||
bind.discoverSongViewPager.setAdapter(discoverSongAdapter);
|
bind.discoverSongRecyclerView.setAdapter(discoverSongAdapter);
|
||||||
bind.discoverSongViewPager.setOffscreenPageLimit(1);
|
|
||||||
homeViewModel.getDiscoverSongSample(getViewLifecycleOwner()).observe(getViewLifecycleOwner(), songs -> {
|
homeViewModel.getDiscoverSongSample(getViewLifecycleOwner()).observe(getViewLifecycleOwner(), songs -> {
|
||||||
MusicUtil.ratingFilter(songs);
|
MusicUtil.ratingFilter(songs);
|
||||||
|
|
||||||
@@ -699,8 +701,6 @@ public class HomeTabMusicFragment extends Fragment implements ClickCallback {
|
|||||||
discoverSongAdapter.setItems(songs);
|
discoverSongAdapter.setItems(songs);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
setSlideViewOffset(bind.discoverSongViewPager, 20, 16);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initSimilarSongView() {
|
private void initSimilarSongView() {
|
||||||
|
|||||||
@@ -26,16 +26,20 @@ import com.cappielloantonio.tempo.helper.recyclerview.CustomLinearSnapHelper;
|
|||||||
import com.cappielloantonio.tempo.interfaces.ClickCallback;
|
import com.cappielloantonio.tempo.interfaces.ClickCallback;
|
||||||
import com.cappielloantonio.tempo.service.MediaManager;
|
import com.cappielloantonio.tempo.service.MediaManager;
|
||||||
import com.cappielloantonio.tempo.service.MediaService;
|
import com.cappielloantonio.tempo.service.MediaService;
|
||||||
|
import com.cappielloantonio.tempo.subsonic.models.Playlist;
|
||||||
import com.cappielloantonio.tempo.ui.activity.MainActivity;
|
import com.cappielloantonio.tempo.ui.activity.MainActivity;
|
||||||
import com.cappielloantonio.tempo.ui.adapter.AlbumAdapter;
|
import com.cappielloantonio.tempo.ui.adapter.AlbumAdapter;
|
||||||
import com.cappielloantonio.tempo.ui.adapter.ArtistAdapter;
|
import com.cappielloantonio.tempo.ui.adapter.ArtistAdapter;
|
||||||
import com.cappielloantonio.tempo.ui.adapter.SongHorizontalAdapter;
|
import com.cappielloantonio.tempo.ui.adapter.SongHorizontalAdapter;
|
||||||
|
import com.cappielloantonio.tempo.ui.adapter.PlaylistHorizontalAdapter;
|
||||||
import com.cappielloantonio.tempo.util.Constants;
|
import com.cappielloantonio.tempo.util.Constants;
|
||||||
import com.cappielloantonio.tempo.viewmodel.PlaybackViewModel;
|
import com.cappielloantonio.tempo.viewmodel.PlaybackViewModel;
|
||||||
import com.cappielloantonio.tempo.viewmodel.SearchViewModel;
|
import com.cappielloantonio.tempo.viewmodel.SearchViewModel;
|
||||||
|
import com.cappielloantonio.tempo.subsonic.models.PlaylistWithSongs;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
public class SearchFragment extends Fragment implements ClickCallback {
|
public class SearchFragment extends Fragment implements ClickCallback {
|
||||||
@@ -49,6 +53,7 @@ public class SearchFragment extends Fragment implements ClickCallback {
|
|||||||
private ArtistAdapter artistAdapter;
|
private ArtistAdapter artistAdapter;
|
||||||
private AlbumAdapter albumAdapter;
|
private AlbumAdapter albumAdapter;
|
||||||
private SongHorizontalAdapter songHorizontalAdapter;
|
private SongHorizontalAdapter songHorizontalAdapter;
|
||||||
|
private PlaylistHorizontalAdapter playlistHorizontalAdapter;
|
||||||
|
|
||||||
private ListenableFuture<MediaBrowser> mediaBrowserListenableFuture;
|
private ListenableFuture<MediaBrowser> mediaBrowserListenableFuture;
|
||||||
|
|
||||||
@@ -126,6 +131,12 @@ public class SearchFragment extends Fragment implements ClickCallback {
|
|||||||
reapplyPlayback();
|
reapplyPlayback();
|
||||||
|
|
||||||
bind.searchResultTracksRecyclerView.setAdapter(songHorizontalAdapter);
|
bind.searchResultTracksRecyclerView.setAdapter(songHorizontalAdapter);
|
||||||
|
|
||||||
|
bind.allsongsview.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||||
|
bind.allsongsview.setHasFixedSize(true);
|
||||||
|
|
||||||
|
playlistHorizontalAdapter = new PlaylistHorizontalAdapter(this);
|
||||||
|
bind.allsongsview.setAdapter(playlistHorizontalAdapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initSearchView() {
|
private void initSearchView() {
|
||||||
@@ -216,13 +227,23 @@ public class SearchFragment extends Fragment implements ClickCallback {
|
|||||||
|
|
||||||
public void search(String query) {
|
public void search(String query) {
|
||||||
searchViewModel.setQuery(query);
|
searchViewModel.setQuery(query);
|
||||||
|
bind.allSongs.setText(this.getView().getContext().getString(R.string.search_all_songs_loading));
|
||||||
|
playlistHorizontalAdapter.setItems(Collections.emptyList());
|
||||||
bind.searchBar.setText(query);
|
bind.searchBar.setText(query);
|
||||||
bind.searchView.hide();
|
bind.searchView.hide();
|
||||||
performSearch(query);
|
performSearch(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateUI(List<Playlist> allSongs) {
|
||||||
|
if (!allSongs.isEmpty()) {
|
||||||
|
playlistHorizontalAdapter.setItems(allSongs);
|
||||||
|
} else {
|
||||||
|
playlistHorizontalAdapter.setItems(Collections.emptyList());
|
||||||
|
}
|
||||||
|
bind.allSongs.setText(this.getView().getContext().getString(R.string.search_all_songs_play,String.valueOf(allSongs.getFirst().getName())));
|
||||||
|
}
|
||||||
private void performSearch(String query) {
|
private void performSearch(String query) {
|
||||||
searchViewModel.search3(query).observe(getViewLifecycleOwner(), result -> {
|
searchViewModel.search3(this, query).observe(getViewLifecycleOwner(), result -> {
|
||||||
if (bind != null) {
|
if (bind != null) {
|
||||||
if (result.getArtists() != null) {
|
if (result.getArtists() != null) {
|
||||||
bind.searchArtistSector.setVisibility(!result.getArtists().isEmpty() ? View.VISIBLE : View.GONE);
|
bind.searchArtistSector.setVisibility(!result.getArtists().isEmpty() ? View.VISIBLE : View.GONE);
|
||||||
@@ -281,6 +302,19 @@ public class SearchFragment extends Fragment implements ClickCallback {
|
|||||||
Navigation.findNavController(requireView()).navigate(R.id.songBottomSheetDialog, bundle);
|
Navigation.findNavController(requireView()).navigate(R.id.songBottomSheetDialog, bundle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlaylistClick(Bundle bundle) {
|
||||||
|
PlaylistWithSongs playlistWithSongs = bundle.getParcelable(Constants.PLAYLIST_OBJECT);
|
||||||
|
if (playlistWithSongs != null) {
|
||||||
|
MediaManager.startQueue(mediaBrowserListenableFuture, playlistWithSongs.getEntries(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlaylistLongClick(Bundle bundle) {
|
||||||
|
Navigation.findNavController(requireView()).navigate(R.id.playlistBottomSheetDialog, bundle);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAlbumClick(Bundle bundle) {
|
public void onAlbumClick(Bundle bundle) {
|
||||||
Navigation.findNavController(requireView()).navigate(R.id.albumPageFragment, bundle);
|
Navigation.findNavController(requireView()).navigate(R.id.albumPageFragment, bundle);
|
||||||
|
|||||||
@@ -0,0 +1,603 @@
|
|||||||
|
package com.cappielloantonio.tempo.ui.fragment;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.ServiceConnection;
|
||||||
|
import android.media.audiofx.AudioEffect;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.text.InputFilter;
|
||||||
|
import android.text.InputType;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.activity.result.ActivityResultLauncher;
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.annotation.OptIn;
|
||||||
|
import androidx.appcompat.app.AppCompatDelegate;
|
||||||
|
import androidx.core.os.LocaleListCompat;
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
import androidx.media3.common.util.UnstableApi;
|
||||||
|
import androidx.navigation.NavController;
|
||||||
|
import androidx.navigation.NavOptions;
|
||||||
|
import androidx.navigation.fragment.NavHostFragment;
|
||||||
|
import androidx.preference.EditTextPreference;
|
||||||
|
import androidx.preference.ListPreference;
|
||||||
|
import androidx.preference.Preference;
|
||||||
|
import androidx.preference.PreferenceCategory;
|
||||||
|
import androidx.preference.PreferenceFragmentCompat;
|
||||||
|
import androidx.preference.SwitchPreference;
|
||||||
|
|
||||||
|
import com.cappielloantonio.tempo.BuildConfig;
|
||||||
|
import com.cappielloantonio.tempo.R;
|
||||||
|
import com.cappielloantonio.tempo.helper.ThemeHelper;
|
||||||
|
import com.cappielloantonio.tempo.interfaces.DialogClickCallback;
|
||||||
|
import com.cappielloantonio.tempo.interfaces.ScanCallback;
|
||||||
|
import com.cappielloantonio.tempo.service.EqualizerManager;
|
||||||
|
import com.cappielloantonio.tempo.service.MediaService;
|
||||||
|
import com.cappielloantonio.tempo.ui.activity.MainActivity;
|
||||||
|
import com.cappielloantonio.tempo.ui.dialog.DeleteDownloadStorageDialog;
|
||||||
|
import com.cappielloantonio.tempo.ui.dialog.DownloadStorageDialog;
|
||||||
|
import com.cappielloantonio.tempo.ui.dialog.StarredAlbumSyncDialog;
|
||||||
|
import com.cappielloantonio.tempo.ui.dialog.StarredArtistSyncDialog;
|
||||||
|
import com.cappielloantonio.tempo.ui.dialog.StarredSyncDialog;
|
||||||
|
import com.cappielloantonio.tempo.ui.dialog.StreamingCacheStorageDialog;
|
||||||
|
import com.cappielloantonio.tempo.util.DownloadUtil;
|
||||||
|
import com.cappielloantonio.tempo.util.ExternalAudioReader;
|
||||||
|
import com.cappielloantonio.tempo.util.Preferences;
|
||||||
|
import com.cappielloantonio.tempo.util.UIUtil;
|
||||||
|
import com.cappielloantonio.tempo.viewmodel.SettingViewModel;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@OptIn(markerClass = UnstableApi.class)
|
||||||
|
public class SettingsContainerFragment extends PreferenceFragmentCompat {
|
||||||
|
|
||||||
|
private static final String TAG = "SettingsFragment";
|
||||||
|
private MainActivity activity;
|
||||||
|
|
||||||
|
private SettingViewModel settingViewModel;
|
||||||
|
|
||||||
|
private ActivityResultLauncher<Intent> directoryPickerLauncher;
|
||||||
|
|
||||||
|
private MediaService.LocalBinder mediaServiceBinder;
|
||||||
|
private boolean isServiceBound = false;
|
||||||
|
private ActivityResultLauncher<Intent> equalizerResultLauncher;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
equalizerResultLauncher = registerForActivityResult(
|
||||||
|
new ActivityResultContracts.StartActivityForResult(),
|
||||||
|
result -> {}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!BuildConfig.FLAVOR.equals("tempus")) {
|
||||||
|
PreferenceCategory githubUpdateCategory = findPreference("settings_github_update_category_key");
|
||||||
|
if (githubUpdateCategory != null) {
|
||||||
|
getPreferenceScreen().removePreference(githubUpdateCategory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
directoryPickerLauncher = registerForActivityResult(
|
||||||
|
new ActivityResultContracts.StartActivityForResult(),
|
||||||
|
result -> {
|
||||||
|
if (result.getResultCode() == Activity.RESULT_OK) {
|
||||||
|
Intent data = result.getData();
|
||||||
|
if (data != null) {
|
||||||
|
Uri uri = data.getData();
|
||||||
|
if (uri != null) {
|
||||||
|
requireContext().getContentResolver().takePersistableUriPermission(
|
||||||
|
uri,
|
||||||
|
Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||||
|
);
|
||||||
|
|
||||||
|
Preferences.setDownloadDirectoryUri(uri.toString());
|
||||||
|
ExternalAudioReader.refreshCache();
|
||||||
|
Toast.makeText(requireContext(), R.string.settings_download_folder_set, Toast.LENGTH_SHORT).show();
|
||||||
|
checkDownloadDirectory();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
activity = (MainActivity) getActivity();
|
||||||
|
|
||||||
|
View view = super.onCreateView(inflater, container, savedInstanceState);
|
||||||
|
settingViewModel = new ViewModelProvider(requireActivity()).get(SettingViewModel.class);
|
||||||
|
|
||||||
|
if (view != null) {
|
||||||
|
getListView().setPadding(0, 0, 0, (int) getResources().getDimension(R.dimen.global_padding_bottom));
|
||||||
|
}
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart() {
|
||||||
|
super.onStart();
|
||||||
|
activity.setBottomNavigationBarVisibility(false);
|
||||||
|
activity.setBottomSheetVisibility(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
|
||||||
|
checkSystemEqualizer();
|
||||||
|
checkCacheStorage();
|
||||||
|
checkStorage();
|
||||||
|
checkDownloadDirectory();
|
||||||
|
|
||||||
|
setStreamingCacheSize();
|
||||||
|
setAppLanguage();
|
||||||
|
setVersion();
|
||||||
|
setNetorkPingTimeoutBase();
|
||||||
|
|
||||||
|
actionLogout();
|
||||||
|
actionScan();
|
||||||
|
actionSyncStarredAlbums();
|
||||||
|
actionSyncStarredTracks();
|
||||||
|
actionSyncStarredArtists();
|
||||||
|
actionChangeStreamingCacheStorage();
|
||||||
|
actionChangeDownloadStorage();
|
||||||
|
actionSetDownloadDirectory();
|
||||||
|
actionDeleteDownloadStorage();
|
||||||
|
actionKeepScreenOn();
|
||||||
|
actionAutoDownloadLyrics();
|
||||||
|
actionMiniPlayerHeart();
|
||||||
|
|
||||||
|
bindMediaService();
|
||||||
|
actionAppEqualizer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||||
|
setPreferencesFromResource(R.xml.global_preferences, rootKey);
|
||||||
|
ListPreference themePreference = findPreference(Preferences.THEME);
|
||||||
|
if (themePreference != null) {
|
||||||
|
themePreference.setOnPreferenceChangeListener(
|
||||||
|
(preference, newValue) -> {
|
||||||
|
String themeOption = (String) newValue;
|
||||||
|
ThemeHelper.applyTheme(themeOption);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkSystemEqualizer() {
|
||||||
|
Preference equalizer = findPreference("system_equalizer");
|
||||||
|
|
||||||
|
if (equalizer == null) return;
|
||||||
|
|
||||||
|
Intent intent = new Intent(AudioEffect.ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL);
|
||||||
|
|
||||||
|
if ((intent.resolveActivity(requireActivity().getPackageManager()) != null)) {
|
||||||
|
equalizer.setOnPreferenceClickListener(preference -> {
|
||||||
|
equalizerResultLauncher.launch(intent);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
equalizer.setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkCacheStorage() {
|
||||||
|
Preference storage = findPreference("streaming_cache_storage");
|
||||||
|
|
||||||
|
if (storage == null) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (requireContext().getExternalFilesDirs(null)[1] == null) {
|
||||||
|
storage.setVisible(false);
|
||||||
|
} else {
|
||||||
|
storage.setSummary(Preferences.getStreamingCacheStoragePreference() == 0 ? R.string.download_storage_internal_dialog_negative_button : R.string.download_storage_external_dialog_positive_button);
|
||||||
|
}
|
||||||
|
} catch (Exception exception) {
|
||||||
|
storage.setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkStorage() {
|
||||||
|
Preference storage = findPreference("download_storage");
|
||||||
|
|
||||||
|
if (storage == null) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (requireContext().getExternalFilesDirs(null)[1] == null) {
|
||||||
|
storage.setVisible(false);
|
||||||
|
} else {
|
||||||
|
int pref = Preferences.getDownloadStoragePreference();
|
||||||
|
if (pref == 0) {
|
||||||
|
storage.setSummary(R.string.download_storage_internal_dialog_negative_button);
|
||||||
|
} else if (pref == 1) {
|
||||||
|
storage.setSummary(R.string.download_storage_external_dialog_positive_button);
|
||||||
|
} else {
|
||||||
|
storage.setSummary(R.string.download_storage_directory_dialog_neutral_button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception exception) {
|
||||||
|
storage.setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkDownloadDirectory() {
|
||||||
|
Preference storage = findPreference("download_storage");
|
||||||
|
Preference directory = findPreference("set_download_directory");
|
||||||
|
|
||||||
|
if (directory == null) return;
|
||||||
|
|
||||||
|
String current = Preferences.getDownloadDirectoryUri();
|
||||||
|
if (current != null) {
|
||||||
|
if (storage != null) storage.setVisible(false);
|
||||||
|
directory.setVisible(true);
|
||||||
|
directory.setIcon(R.drawable.ic_close);
|
||||||
|
directory.setTitle(R.string.settings_clear_download_folder);
|
||||||
|
directory.setSummary(current);
|
||||||
|
} else {
|
||||||
|
if (storage != null) storage.setVisible(true);
|
||||||
|
if (Preferences.getDownloadStoragePreference() == 2) {
|
||||||
|
directory.setVisible(true);
|
||||||
|
directory.setIcon(R.drawable.ic_folder);
|
||||||
|
directory.setTitle(R.string.settings_set_download_folder);
|
||||||
|
directory.setSummary(R.string.settings_choose_download_folder);
|
||||||
|
} else {
|
||||||
|
directory.setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setNetorkPingTimeoutBase() {
|
||||||
|
EditTextPreference networkPingTimeoutBase = findPreference("network_ping_timeout_base");
|
||||||
|
|
||||||
|
if (networkPingTimeoutBase != null) {
|
||||||
|
networkPingTimeoutBase.setSummaryProvider(EditTextPreference.SimpleSummaryProvider.getInstance());
|
||||||
|
networkPingTimeoutBase.setOnBindEditTextListener(editText -> {
|
||||||
|
editText.setInputType(InputType.TYPE_CLASS_NUMBER);
|
||||||
|
editText.setFilters(new InputFilter[]{ (source, start, end, dest, dstart, dend) -> {
|
||||||
|
for (int i = start; i < end; i++) {
|
||||||
|
if (!Character.isDigit(source.charAt(i))) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}});
|
||||||
|
});
|
||||||
|
|
||||||
|
networkPingTimeoutBase.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||||
|
String input = (String) newValue;
|
||||||
|
return input != null && !input.isEmpty();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setStreamingCacheSize() {
|
||||||
|
ListPreference streamingCachePreference = findPreference("streaming_cache_size");
|
||||||
|
|
||||||
|
if (streamingCachePreference != null) {
|
||||||
|
streamingCachePreference.setSummaryProvider(new Preference.SummaryProvider<ListPreference>() {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public CharSequence provideSummary(@NonNull ListPreference preference) {
|
||||||
|
CharSequence entry = preference.getEntry();
|
||||||
|
|
||||||
|
if (entry == null) return null;
|
||||||
|
|
||||||
|
long currentSizeMb = DownloadUtil.getStreamingCacheSize(requireActivity()) / (1024 * 1024);
|
||||||
|
|
||||||
|
return getString(R.string.settings_summary_streaming_cache_size, entry, String.valueOf(currentSizeMb));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setAppLanguage() {
|
||||||
|
ListPreference localePref = (ListPreference) findPreference("language");
|
||||||
|
|
||||||
|
Map<String, String> locales = UIUtil.getLangPreferenceDropdownEntries(requireContext());
|
||||||
|
|
||||||
|
CharSequence[] entries = locales.keySet().toArray(new CharSequence[locales.size()]);
|
||||||
|
CharSequence[] entryValues = locales.values().toArray(new CharSequence[locales.size()]);
|
||||||
|
|
||||||
|
localePref.setEntries(entries);
|
||||||
|
localePref.setEntryValues(entryValues);
|
||||||
|
|
||||||
|
String value = localePref.getValue();
|
||||||
|
if ("default".equals(value)) {
|
||||||
|
localePref.setSummary(requireContext().getString(R.string.settings_system_language));
|
||||||
|
} else {
|
||||||
|
localePref.setSummary(Locale.forLanguageTag(value).getDisplayName());
|
||||||
|
}
|
||||||
|
|
||||||
|
localePref.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||||
|
if ("default".equals(newValue)) {
|
||||||
|
AppCompatDelegate.setApplicationLocales(LocaleListCompat.getEmptyLocaleList());
|
||||||
|
preference.setSummary(requireContext().getString(R.string.settings_system_language));
|
||||||
|
} else {
|
||||||
|
LocaleListCompat appLocale = LocaleListCompat.forLanguageTags((String) newValue);
|
||||||
|
AppCompatDelegate.setApplicationLocales(appLocale);
|
||||||
|
preference.setSummary(Locale.forLanguageTag((String) newValue).getDisplayName());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setVersion() {
|
||||||
|
findPreference("version").setSummary(BuildConfig.VERSION_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void actionLogout() {
|
||||||
|
findPreference("logout").setOnPreferenceClickListener(preference -> {
|
||||||
|
activity.quit();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void actionScan() {
|
||||||
|
findPreference("scan_library").setOnPreferenceClickListener(preference -> {
|
||||||
|
settingViewModel.launchScan(new ScanCallback() {
|
||||||
|
@Override
|
||||||
|
public void onError(Exception exception) {
|
||||||
|
findPreference("scan_library").setSummary(exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuccess(boolean isScanning, long count) {
|
||||||
|
findPreference("scan_library").setSummary(getString(R.string.settings_scan_result, count));
|
||||||
|
if (isScanning) getScanStatus();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void actionSyncStarredTracks() {
|
||||||
|
findPreference("sync_starred_tracks_for_offline_use").setOnPreferenceChangeListener((preference, newValue) -> {
|
||||||
|
if (newValue instanceof Boolean) {
|
||||||
|
if ((Boolean) newValue) {
|
||||||
|
StarredSyncDialog dialog = new StarredSyncDialog(() -> {
|
||||||
|
((SwitchPreference)preference).setChecked(false);
|
||||||
|
});
|
||||||
|
dialog.show(activity.getSupportFragmentManager(), null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void actionSyncStarredAlbums() {
|
||||||
|
findPreference("sync_starred_albums_for_offline_use").setOnPreferenceChangeListener((preference, newValue) -> {
|
||||||
|
if (newValue instanceof Boolean) {
|
||||||
|
if ((Boolean) newValue) {
|
||||||
|
StarredAlbumSyncDialog dialog = new StarredAlbumSyncDialog(() -> {
|
||||||
|
((SwitchPreference)preference).setChecked(false);
|
||||||
|
});
|
||||||
|
dialog.show(activity.getSupportFragmentManager(), null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void actionSyncStarredArtists() {
|
||||||
|
findPreference("sync_starred_artists_for_offline_use").setOnPreferenceChangeListener((preference, newValue) -> {
|
||||||
|
if (newValue instanceof Boolean) {
|
||||||
|
if ((Boolean) newValue) {
|
||||||
|
StarredArtistSyncDialog dialog = new StarredArtistSyncDialog(() -> {
|
||||||
|
((SwitchPreference)preference).setChecked(false);
|
||||||
|
});
|
||||||
|
dialog.show(activity.getSupportFragmentManager(), null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void actionChangeStreamingCacheStorage() {
|
||||||
|
findPreference("streaming_cache_storage").setOnPreferenceClickListener(preference -> {
|
||||||
|
StreamingCacheStorageDialog dialog = new StreamingCacheStorageDialog(new DialogClickCallback() {
|
||||||
|
@Override
|
||||||
|
public void onPositiveClick() {
|
||||||
|
findPreference("streaming_cache_storage").setSummary(R.string.streaming_cache_storage_external_dialog_positive_button);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNegativeClick() {
|
||||||
|
findPreference("streaming_cache_storage").setSummary(R.string.streaming_cache_storage_internal_dialog_negative_button);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
dialog.show(activity.getSupportFragmentManager(), null);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void actionChangeDownloadStorage() {
|
||||||
|
findPreference("download_storage").setOnPreferenceClickListener(preference -> {
|
||||||
|
DownloadStorageDialog dialog = new DownloadStorageDialog(new DialogClickCallback() {
|
||||||
|
@Override
|
||||||
|
public void onPositiveClick() {
|
||||||
|
findPreference("download_storage").setSummary(R.string.download_storage_external_dialog_positive_button);
|
||||||
|
checkDownloadDirectory();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNegativeClick() {
|
||||||
|
findPreference("download_storage").setSummary(R.string.download_storage_internal_dialog_negative_button);
|
||||||
|
checkDownloadDirectory();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNeutralClick() {
|
||||||
|
findPreference("download_storage").setSummary(R.string.download_storage_directory_dialog_neutral_button);
|
||||||
|
checkDownloadDirectory();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
dialog.show(activity.getSupportFragmentManager(), null);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void actionSetDownloadDirectory() {
|
||||||
|
Preference pref = findPreference("set_download_directory");
|
||||||
|
if (pref != null) {
|
||||||
|
pref.setOnPreferenceClickListener(preference -> {
|
||||||
|
String current = Preferences.getDownloadDirectoryUri();
|
||||||
|
|
||||||
|
if (current != null) {
|
||||||
|
Preferences.setDownloadDirectoryUri(null);
|
||||||
|
Preferences.setDownloadStoragePreference(0);
|
||||||
|
ExternalAudioReader.refreshCache();
|
||||||
|
Toast.makeText(requireContext(), R.string.settings_download_folder_cleared, Toast.LENGTH_SHORT).show();
|
||||||
|
checkStorage();
|
||||||
|
checkDownloadDirectory();
|
||||||
|
} else {
|
||||||
|
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
|
||||||
|
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
|
||||||
|
| Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||||
|
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||||
|
directoryPickerLauncher.launch(intent);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void actionDeleteDownloadStorage() {
|
||||||
|
findPreference("delete_download_storage").setOnPreferenceClickListener(preference -> {
|
||||||
|
DeleteDownloadStorageDialog dialog = new DeleteDownloadStorageDialog();
|
||||||
|
dialog.show(activity.getSupportFragmentManager(), null);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void actionMiniPlayerHeart() {
|
||||||
|
SwitchPreference preference = findPreference("mini_shuffle_button_visibility");
|
||||||
|
if (preference == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
preference.setChecked(Preferences.showShuffleInsteadOfHeart());
|
||||||
|
preference.setOnPreferenceChangeListener((pref, newValue) -> {
|
||||||
|
if (newValue instanceof Boolean) {
|
||||||
|
Preferences.setShuffleInsteadOfHeart((Boolean) newValue);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void actionAutoDownloadLyrics() {
|
||||||
|
SwitchPreference preference = findPreference("auto_download_lyrics");
|
||||||
|
if (preference == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
preference.setChecked(Preferences.isAutoDownloadLyricsEnabled());
|
||||||
|
preference.setOnPreferenceChangeListener((pref, newValue) -> {
|
||||||
|
if (newValue instanceof Boolean) {
|
||||||
|
Preferences.setAutoDownloadLyricsEnabled((Boolean) newValue);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getScanStatus() {
|
||||||
|
settingViewModel.getScanStatus(new ScanCallback() {
|
||||||
|
@Override
|
||||||
|
public void onError(Exception exception) {
|
||||||
|
findPreference("scan_library").setSummary(exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuccess(boolean isScanning, long count) {
|
||||||
|
findPreference("scan_library").setSummary(getString(R.string.settings_scan_result, count));
|
||||||
|
if (isScanning) getScanStatus();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void actionKeepScreenOn() {
|
||||||
|
findPreference("always_on_display").setOnPreferenceChangeListener((preference, newValue) -> {
|
||||||
|
if (newValue instanceof Boolean) {
|
||||||
|
if ((Boolean) newValue) {
|
||||||
|
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||||
|
} else {
|
||||||
|
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private final ServiceConnection serviceConnection = new ServiceConnection() {
|
||||||
|
@Override
|
||||||
|
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||||
|
mediaServiceBinder = (MediaService.LocalBinder) service;
|
||||||
|
isServiceBound = true;
|
||||||
|
checkEqualizerBands();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServiceDisconnected(ComponentName name) {
|
||||||
|
mediaServiceBinder = null;
|
||||||
|
isServiceBound = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private void bindMediaService() {
|
||||||
|
Intent intent = new Intent(requireActivity(), MediaService.class);
|
||||||
|
intent.setAction(MediaService.ACTION_BIND_EQUALIZER);
|
||||||
|
requireActivity().bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
|
||||||
|
isServiceBound = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkEqualizerBands() {
|
||||||
|
if (mediaServiceBinder != null) {
|
||||||
|
EqualizerManager eqManager = mediaServiceBinder.getEqualizerManager();
|
||||||
|
short numBands = eqManager.getNumberOfBands();
|
||||||
|
Preference appEqualizer = findPreference("app_equalizer");
|
||||||
|
if (appEqualizer != null) {
|
||||||
|
appEqualizer.setVisible(numBands > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void actionAppEqualizer() {
|
||||||
|
Preference appEqualizer = findPreference("app_equalizer");
|
||||||
|
if (appEqualizer != null) {
|
||||||
|
appEqualizer.setOnPreferenceClickListener(preference -> {
|
||||||
|
NavController navController = NavHostFragment.findNavController(this);
|
||||||
|
NavOptions navOptions = new NavOptions.Builder()
|
||||||
|
.setLaunchSingleTop(true)
|
||||||
|
.setPopUpTo(R.id.equalizerFragment, true)
|
||||||
|
.build();
|
||||||
|
activity.setBottomNavigationBarVisibility(true);
|
||||||
|
activity.setBottomSheetVisibility(true);
|
||||||
|
navController.navigate(R.id.equalizerFragment, null, navOptions);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
if (isServiceBound) {
|
||||||
|
requireActivity().unbindService(serviceConnection);
|
||||||
|
isServiceBound = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,128 +1,61 @@
|
|||||||
package com.cappielloantonio.tempo.ui.fragment;
|
package com.cappielloantonio.tempo.ui.fragment;
|
||||||
|
|
||||||
import android.app.Activity;
|
import static com.google.android.material.internal.ViewUtils.hideKeyboard;
|
||||||
import android.content.Context;
|
|
||||||
import android.content.ComponentName;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.ServiceConnection;
|
|
||||||
import android.media.audiofx.AudioEffect;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
|
||||||
import android.text.InputFilter;
|
|
||||||
import android.text.InputType;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.WindowManager;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import androidx.activity.result.ActivityResultLauncher;
|
|
||||||
import androidx.activity.result.contract.ActivityResultContracts;
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.OptIn;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.appcompat.app.AppCompatDelegate;
|
|
||||||
import androidx.core.os.LocaleListCompat;
|
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
|
||||||
import androidx.media3.common.util.UnstableApi;
|
|
||||||
import androidx.navigation.NavController;
|
|
||||||
import androidx.navigation.NavOptions;
|
|
||||||
import androidx.navigation.fragment.NavHostFragment;
|
|
||||||
import androidx.preference.EditTextPreference;
|
|
||||||
import androidx.preference.ListPreference;
|
|
||||||
import androidx.preference.Preference;
|
|
||||||
import androidx.preference.PreferenceCategory;
|
|
||||||
import androidx.preference.PreferenceFragmentCompat;
|
|
||||||
import androidx.preference.SwitchPreference;
|
|
||||||
|
|
||||||
import com.cappielloantonio.tempo.BuildConfig;
|
|
||||||
import com.cappielloantonio.tempo.R;
|
import com.cappielloantonio.tempo.R;
|
||||||
import com.cappielloantonio.tempo.helper.ThemeHelper;
|
import com.cappielloantonio.tempo.databinding.FragmentSettingsBinding;
|
||||||
import com.cappielloantonio.tempo.interfaces.DialogClickCallback;
|
|
||||||
import com.cappielloantonio.tempo.interfaces.ScanCallback;
|
|
||||||
import com.cappielloantonio.tempo.service.EqualizerManager;
|
|
||||||
import com.cappielloantonio.tempo.service.MediaService;
|
|
||||||
import com.cappielloantonio.tempo.ui.activity.MainActivity;
|
import com.cappielloantonio.tempo.ui.activity.MainActivity;
|
||||||
import com.cappielloantonio.tempo.ui.dialog.DeleteDownloadStorageDialog;
|
|
||||||
import com.cappielloantonio.tempo.ui.dialog.DownloadStorageDialog;
|
|
||||||
import com.cappielloantonio.tempo.ui.dialog.StarredSyncDialog;
|
|
||||||
import com.cappielloantonio.tempo.ui.dialog.StarredAlbumSyncDialog;
|
|
||||||
import com.cappielloantonio.tempo.ui.dialog.StarredArtistSyncDialog;
|
|
||||||
import com.cappielloantonio.tempo.ui.dialog.StreamingCacheStorageDialog;
|
|
||||||
import com.cappielloantonio.tempo.util.DownloadUtil;
|
|
||||||
import com.cappielloantonio.tempo.util.Preferences;
|
import com.cappielloantonio.tempo.util.Preferences;
|
||||||
import com.cappielloantonio.tempo.util.UIUtil;
|
|
||||||
import com.cappielloantonio.tempo.util.ExternalAudioReader;
|
|
||||||
import com.cappielloantonio.tempo.viewmodel.SettingViewModel;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
public class SettingsFragment extends Fragment {
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@OptIn(markerClass = UnstableApi.class)
|
|
||||||
public class SettingsFragment extends PreferenceFragmentCompat {
|
|
||||||
private static final String TAG = "SettingsFragment";
|
|
||||||
|
|
||||||
private MainActivity activity;
|
private MainActivity activity;
|
||||||
private SettingViewModel settingViewModel;
|
private FragmentSettingsBinding bind;
|
||||||
|
|
||||||
private ActivityResultLauncher<Intent> equalizerResultLauncher;
|
|
||||||
private ActivityResultLauncher<Intent> directoryPickerLauncher;
|
|
||||||
|
|
||||||
private MediaService.LocalBinder mediaServiceBinder;
|
|
||||||
private boolean isServiceBound = false;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
equalizerResultLauncher = registerForActivityResult(
|
activity = (MainActivity) getActivity();
|
||||||
new ActivityResultContracts.StartActivityForResult(),
|
|
||||||
result -> {}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!BuildConfig.FLAVOR.equals("tempus")) {
|
|
||||||
PreferenceCategory githubUpdateCategory = findPreference("settings_github_update_category_key");
|
|
||||||
if (githubUpdateCategory != null) {
|
|
||||||
getPreferenceScreen().removePreference(githubUpdateCategory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
directoryPickerLauncher = registerForActivityResult(
|
|
||||||
new ActivityResultContracts.StartActivityForResult(),
|
|
||||||
result -> {
|
|
||||||
if (result.getResultCode() == Activity.RESULT_OK) {
|
|
||||||
Intent data = result.getData();
|
|
||||||
if (data != null) {
|
|
||||||
Uri uri = data.getData();
|
|
||||||
if (uri != null) {
|
|
||||||
requireContext().getContentResolver().takePersistableUriPermission(
|
|
||||||
uri,
|
|
||||||
Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
|
||||||
);
|
|
||||||
|
|
||||||
Preferences.setDownloadDirectoryUri(uri.toString());
|
|
||||||
ExternalAudioReader.refreshCache();
|
|
||||||
Toast.makeText(requireContext(), R.string.settings_download_folder_set, Toast.LENGTH_SHORT).show();
|
|
||||||
checkDownloadDirectory();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
activity = (MainActivity) getActivity();
|
bind = FragmentSettingsBinding.inflate(inflater,container,false);
|
||||||
|
View view = bind.getRoot();
|
||||||
|
|
||||||
View view = super.onCreateView(inflater, container, savedInstanceState);
|
initAppBar();
|
||||||
settingViewModel = new ViewModelProvider(requireActivity()).get(SettingViewModel.class);
|
|
||||||
|
|
||||||
if (view != null) {
|
|
||||||
getListView().setPadding(0, 0, 0, (int) getResources().getDimension(R.dimen.global_padding_bottom));
|
|
||||||
}
|
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(@NonNull View view,
|
||||||
|
@Nullable Bundle savedInstanceState) {
|
||||||
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
|
||||||
|
// Add the PreferenceFragment only the first time
|
||||||
|
if (savedInstanceState == null) {
|
||||||
|
SettingsContainerFragment prefFragment = new SettingsContainerFragment();
|
||||||
|
|
||||||
|
// Use the child fragment manager so the PreferenceFragment is scoped to this fragment
|
||||||
|
getChildFragmentManager()
|
||||||
|
.beginTransaction()
|
||||||
|
.replace(R.id.settings_container, prefFragment)
|
||||||
|
.setReorderingAllowed(true) // optional but recommended
|
||||||
|
.commit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -134,479 +67,21 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
|||||||
activity.setSystemBarsVisibility(!activity.isLandscape);
|
activity.setSystemBarsVisibility(!activity.isLandscape);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
|
|
||||||
checkSystemEqualizer();
|
|
||||||
checkCacheStorage();
|
|
||||||
checkStorage();
|
|
||||||
checkDownloadDirectory();
|
|
||||||
|
|
||||||
setStreamingCacheSize();
|
|
||||||
setAppLanguage();
|
|
||||||
setVersion();
|
|
||||||
setNetorkPingTimeoutBase();
|
|
||||||
|
|
||||||
actionLogout();
|
|
||||||
actionScan();
|
|
||||||
actionSyncStarredAlbums();
|
|
||||||
actionSyncStarredTracks();
|
|
||||||
actionSyncStarredArtists();
|
|
||||||
actionChangeStreamingCacheStorage();
|
|
||||||
actionChangeDownloadStorage();
|
|
||||||
actionSetDownloadDirectory();
|
|
||||||
actionDeleteDownloadStorage();
|
|
||||||
actionKeepScreenOn();
|
|
||||||
actionAutoDownloadLyrics();
|
|
||||||
actionMiniPlayerHeart();
|
|
||||||
|
|
||||||
bindMediaService();
|
|
||||||
actionAppEqualizer();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStop() {
|
public void onStop() {
|
||||||
super.onStop();
|
super.onStop();
|
||||||
activity.setBottomSheetVisibility(true);
|
activity.setBottomSheetVisibility(true);
|
||||||
activity.toggleNavigationDrawerLockOnOrientationChange();
|
|
||||||
activity.setSystemBarsVisibility(!activity.isLandscape);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
if (activity.isLandscape) {
|
||||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
activity.setNavigationDrawerLock(false);
|
||||||
setPreferencesFromResource(R.xml.global_preferences, rootKey);
|
} else if (Preferences.getEnableDrawerOnPortrait()) {
|
||||||
ListPreference themePreference = findPreference(Preferences.THEME);
|
activity.setNavigationDrawerLock(false);
|
||||||
if (themePreference != null) {
|
|
||||||
themePreference.setOnPreferenceChangeListener(
|
|
||||||
(preference, newValue) -> {
|
|
||||||
String themeOption = (String) newValue;
|
|
||||||
ThemeHelper.applyTheme(themeOption);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkSystemEqualizer() {
|
private void initAppBar() {
|
||||||
Preference equalizer = findPreference("system_equalizer");
|
bind.settingsToolbar.setNavigationOnClickListener(v -> {
|
||||||
|
activity.navController.navigateUp();
|
||||||
if (equalizer == null) return;
|
|
||||||
|
|
||||||
Intent intent = new Intent(AudioEffect.ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL);
|
|
||||||
|
|
||||||
if ((intent.resolveActivity(requireActivity().getPackageManager()) != null)) {
|
|
||||||
equalizer.setOnPreferenceClickListener(preference -> {
|
|
||||||
equalizerResultLauncher.launch(intent);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
equalizer.setVisible(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkCacheStorage() {
|
|
||||||
Preference storage = findPreference("streaming_cache_storage");
|
|
||||||
|
|
||||||
if (storage == null) return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (requireContext().getExternalFilesDirs(null)[1] == null) {
|
|
||||||
storage.setVisible(false);
|
|
||||||
} else {
|
|
||||||
storage.setSummary(Preferences.getStreamingCacheStoragePreference() == 0 ? R.string.download_storage_internal_dialog_negative_button : R.string.download_storage_external_dialog_positive_button);
|
|
||||||
}
|
|
||||||
} catch (Exception exception) {
|
|
||||||
storage.setVisible(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkStorage() {
|
|
||||||
Preference storage = findPreference("download_storage");
|
|
||||||
|
|
||||||
if (storage == null) return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (requireContext().getExternalFilesDirs(null)[1] == null) {
|
|
||||||
storage.setVisible(false);
|
|
||||||
} else {
|
|
||||||
int pref = Preferences.getDownloadStoragePreference();
|
|
||||||
if (pref == 0) {
|
|
||||||
storage.setSummary(R.string.download_storage_internal_dialog_negative_button);
|
|
||||||
} else if (pref == 1) {
|
|
||||||
storage.setSummary(R.string.download_storage_external_dialog_positive_button);
|
|
||||||
} else {
|
|
||||||
storage.setSummary(R.string.download_storage_directory_dialog_neutral_button);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception exception) {
|
|
||||||
storage.setVisible(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkDownloadDirectory() {
|
|
||||||
Preference storage = findPreference("download_storage");
|
|
||||||
Preference directory = findPreference("set_download_directory");
|
|
||||||
|
|
||||||
if (directory == null) return;
|
|
||||||
|
|
||||||
String current = Preferences.getDownloadDirectoryUri();
|
|
||||||
if (current != null) {
|
|
||||||
if (storage != null) storage.setVisible(false);
|
|
||||||
directory.setVisible(true);
|
|
||||||
directory.setIcon(R.drawable.ic_close);
|
|
||||||
directory.setTitle(R.string.settings_clear_download_folder);
|
|
||||||
directory.setSummary(current);
|
|
||||||
} else {
|
|
||||||
if (storage != null) storage.setVisible(true);
|
|
||||||
if (Preferences.getDownloadStoragePreference() == 2) {
|
|
||||||
directory.setVisible(true);
|
|
||||||
directory.setIcon(R.drawable.ic_folder);
|
|
||||||
directory.setTitle(R.string.settings_set_download_folder);
|
|
||||||
directory.setSummary(R.string.settings_choose_download_folder);
|
|
||||||
} else {
|
|
||||||
directory.setVisible(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setNetorkPingTimeoutBase() {
|
|
||||||
EditTextPreference networkPingTimeoutBase = findPreference("network_ping_timeout_base");
|
|
||||||
|
|
||||||
if (networkPingTimeoutBase != null) {
|
|
||||||
networkPingTimeoutBase.setSummaryProvider(EditTextPreference.SimpleSummaryProvider.getInstance());
|
|
||||||
networkPingTimeoutBase.setOnBindEditTextListener(editText -> {
|
|
||||||
editText.setInputType(InputType.TYPE_CLASS_NUMBER);
|
|
||||||
editText.setFilters(new InputFilter[]{ (source, start, end, dest, dstart, dend) -> {
|
|
||||||
for (int i = start; i < end; i++) {
|
|
||||||
if (!Character.isDigit(source.charAt(i))) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
networkPingTimeoutBase.setOnPreferenceChangeListener((preference, newValue) -> {
|
|
||||||
String input = (String) newValue;
|
|
||||||
return input != null && !input.isEmpty();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setStreamingCacheSize() {
|
|
||||||
ListPreference streamingCachePreference = findPreference("streaming_cache_size");
|
|
||||||
|
|
||||||
if (streamingCachePreference != null) {
|
|
||||||
streamingCachePreference.setSummaryProvider(new Preference.SummaryProvider<ListPreference>() {
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public CharSequence provideSummary(@NonNull ListPreference preference) {
|
|
||||||
CharSequence entry = preference.getEntry();
|
|
||||||
|
|
||||||
if (entry == null) return null;
|
|
||||||
|
|
||||||
long currentSizeMb = DownloadUtil.getStreamingCacheSize(requireActivity()) / (1024 * 1024);
|
|
||||||
|
|
||||||
return getString(R.string.settings_summary_streaming_cache_size, entry, String.valueOf(currentSizeMb));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setAppLanguage() {
|
|
||||||
ListPreference localePref = (ListPreference) findPreference("language");
|
|
||||||
|
|
||||||
Map<String, String> locales = UIUtil.getLangPreferenceDropdownEntries(requireContext());
|
|
||||||
|
|
||||||
CharSequence[] entries = locales.keySet().toArray(new CharSequence[locales.size()]);
|
|
||||||
CharSequence[] entryValues = locales.values().toArray(new CharSequence[locales.size()]);
|
|
||||||
|
|
||||||
localePref.setEntries(entries);
|
|
||||||
localePref.setEntryValues(entryValues);
|
|
||||||
|
|
||||||
String value = localePref.getValue();
|
|
||||||
if ("default".equals(value)) {
|
|
||||||
localePref.setSummary(requireContext().getString(R.string.settings_system_language));
|
|
||||||
} else {
|
|
||||||
localePref.setSummary(Locale.forLanguageTag(value).getDisplayName());
|
|
||||||
}
|
|
||||||
|
|
||||||
localePref.setOnPreferenceChangeListener((preference, newValue) -> {
|
|
||||||
if ("default".equals(newValue)) {
|
|
||||||
AppCompatDelegate.setApplicationLocales(LocaleListCompat.getEmptyLocaleList());
|
|
||||||
preference.setSummary(requireContext().getString(R.string.settings_system_language));
|
|
||||||
} else {
|
|
||||||
LocaleListCompat appLocale = LocaleListCompat.forLanguageTags((String) newValue);
|
|
||||||
AppCompatDelegate.setApplicationLocales(appLocale);
|
|
||||||
preference.setSummary(Locale.forLanguageTag((String) newValue).getDisplayName());
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setVersion() {
|
|
||||||
findPreference("version").setSummary(BuildConfig.VERSION_NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void actionLogout() {
|
|
||||||
findPreference("logout").setOnPreferenceClickListener(preference -> {
|
|
||||||
activity.quit();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void actionScan() {
|
|
||||||
findPreference("scan_library").setOnPreferenceClickListener(preference -> {
|
|
||||||
settingViewModel.launchScan(new ScanCallback() {
|
|
||||||
@Override
|
|
||||||
public void onError(Exception exception) {
|
|
||||||
findPreference("scan_library").setSummary(exception.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSuccess(boolean isScanning, long count) {
|
|
||||||
findPreference("scan_library").setSummary(getString(R.string.settings_scan_result, count));
|
|
||||||
if (isScanning) getScanStatus();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void actionSyncStarredTracks() {
|
|
||||||
findPreference("sync_starred_tracks_for_offline_use").setOnPreferenceChangeListener((preference, newValue) -> {
|
|
||||||
if (newValue instanceof Boolean) {
|
|
||||||
if ((Boolean) newValue) {
|
|
||||||
StarredSyncDialog dialog = new StarredSyncDialog(() -> {
|
|
||||||
((SwitchPreference)preference).setChecked(false);
|
|
||||||
});
|
|
||||||
dialog.show(activity.getSupportFragmentManager(), null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void actionSyncStarredAlbums() {
|
|
||||||
findPreference("sync_starred_albums_for_offline_use").setOnPreferenceChangeListener((preference, newValue) -> {
|
|
||||||
if (newValue instanceof Boolean) {
|
|
||||||
if ((Boolean) newValue) {
|
|
||||||
StarredAlbumSyncDialog dialog = new StarredAlbumSyncDialog(() -> {
|
|
||||||
((SwitchPreference)preference).setChecked(false);
|
|
||||||
});
|
|
||||||
dialog.show(activity.getSupportFragmentManager(), null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void actionSyncStarredArtists() {
|
|
||||||
findPreference("sync_starred_artists_for_offline_use").setOnPreferenceChangeListener((preference, newValue) -> {
|
|
||||||
if (newValue instanceof Boolean) {
|
|
||||||
if ((Boolean) newValue) {
|
|
||||||
StarredArtistSyncDialog dialog = new StarredArtistSyncDialog(() -> {
|
|
||||||
((SwitchPreference)preference).setChecked(false);
|
|
||||||
});
|
|
||||||
dialog.show(activity.getSupportFragmentManager(), null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void actionChangeStreamingCacheStorage() {
|
|
||||||
findPreference("streaming_cache_storage").setOnPreferenceClickListener(preference -> {
|
|
||||||
StreamingCacheStorageDialog dialog = new StreamingCacheStorageDialog(new DialogClickCallback() {
|
|
||||||
@Override
|
|
||||||
public void onPositiveClick() {
|
|
||||||
findPreference("streaming_cache_storage").setSummary(R.string.streaming_cache_storage_external_dialog_positive_button);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNegativeClick() {
|
|
||||||
findPreference("streaming_cache_storage").setSummary(R.string.streaming_cache_storage_internal_dialog_negative_button);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
dialog.show(activity.getSupportFragmentManager(), null);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void actionChangeDownloadStorage() {
|
|
||||||
findPreference("download_storage").setOnPreferenceClickListener(preference -> {
|
|
||||||
DownloadStorageDialog dialog = new DownloadStorageDialog(new DialogClickCallback() {
|
|
||||||
@Override
|
|
||||||
public void onPositiveClick() {
|
|
||||||
findPreference("download_storage").setSummary(R.string.download_storage_external_dialog_positive_button);
|
|
||||||
checkDownloadDirectory();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNegativeClick() {
|
|
||||||
findPreference("download_storage").setSummary(R.string.download_storage_internal_dialog_negative_button);
|
|
||||||
checkDownloadDirectory();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNeutralClick() {
|
|
||||||
findPreference("download_storage").setSummary(R.string.download_storage_directory_dialog_neutral_button);
|
|
||||||
checkDownloadDirectory();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
dialog.show(activity.getSupportFragmentManager(), null);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void actionSetDownloadDirectory() {
|
|
||||||
Preference pref = findPreference("set_download_directory");
|
|
||||||
if (pref != null) {
|
|
||||||
pref.setOnPreferenceClickListener(preference -> {
|
|
||||||
String current = Preferences.getDownloadDirectoryUri();
|
|
||||||
|
|
||||||
if (current != null) {
|
|
||||||
Preferences.setDownloadDirectoryUri(null);
|
|
||||||
Preferences.setDownloadStoragePreference(0);
|
|
||||||
ExternalAudioReader.refreshCache();
|
|
||||||
Toast.makeText(requireContext(), R.string.settings_download_folder_cleared, Toast.LENGTH_SHORT).show();
|
|
||||||
checkStorage();
|
|
||||||
checkDownloadDirectory();
|
|
||||||
} else {
|
|
||||||
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
|
|
||||||
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
|
|
||||||
| Intent.FLAG_GRANT_READ_URI_PERMISSION
|
|
||||||
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
|
||||||
directoryPickerLauncher.launch(intent);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void actionDeleteDownloadStorage() {
|
|
||||||
findPreference("delete_download_storage").setOnPreferenceClickListener(preference -> {
|
|
||||||
DeleteDownloadStorageDialog dialog = new DeleteDownloadStorageDialog();
|
|
||||||
dialog.show(activity.getSupportFragmentManager(), null);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void actionMiniPlayerHeart() {
|
|
||||||
SwitchPreference preference = findPreference("mini_shuffle_button_visibility");
|
|
||||||
if (preference == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
preference.setChecked(Preferences.showShuffleInsteadOfHeart());
|
|
||||||
preference.setOnPreferenceChangeListener((pref, newValue) -> {
|
|
||||||
if (newValue instanceof Boolean) {
|
|
||||||
Preferences.setShuffleInsteadOfHeart((Boolean) newValue);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void actionAutoDownloadLyrics() {
|
|
||||||
SwitchPreference preference = findPreference("auto_download_lyrics");
|
|
||||||
if (preference == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
preference.setChecked(Preferences.isAutoDownloadLyricsEnabled());
|
|
||||||
preference.setOnPreferenceChangeListener((pref, newValue) -> {
|
|
||||||
if (newValue instanceof Boolean) {
|
|
||||||
Preferences.setAutoDownloadLyricsEnabled((Boolean) newValue);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void getScanStatus() {
|
|
||||||
settingViewModel.getScanStatus(new ScanCallback() {
|
|
||||||
@Override
|
|
||||||
public void onError(Exception exception) {
|
|
||||||
findPreference("scan_library").setSummary(exception.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSuccess(boolean isScanning, long count) {
|
|
||||||
findPreference("scan_library").setSummary(getString(R.string.settings_scan_result, count));
|
|
||||||
if (isScanning) getScanStatus();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void actionKeepScreenOn() {
|
|
||||||
findPreference("always_on_display").setOnPreferenceChangeListener((preference, newValue) -> {
|
|
||||||
if (newValue instanceof Boolean) {
|
|
||||||
if ((Boolean) newValue) {
|
|
||||||
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
|
||||||
} else {
|
|
||||||
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private final ServiceConnection serviceConnection = new ServiceConnection() {
|
|
||||||
@Override
|
|
||||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
|
||||||
mediaServiceBinder = (MediaService.LocalBinder) service;
|
|
||||||
isServiceBound = true;
|
|
||||||
checkEqualizerBands();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onServiceDisconnected(ComponentName name) {
|
|
||||||
mediaServiceBinder = null;
|
|
||||||
isServiceBound = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private void bindMediaService() {
|
|
||||||
Intent intent = new Intent(requireActivity(), MediaService.class);
|
|
||||||
intent.setAction(MediaService.ACTION_BIND_EQUALIZER);
|
|
||||||
requireActivity().bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
|
|
||||||
isServiceBound = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkEqualizerBands() {
|
|
||||||
if (mediaServiceBinder != null) {
|
|
||||||
EqualizerManager eqManager = mediaServiceBinder.getEqualizerManager();
|
|
||||||
short numBands = eqManager.getNumberOfBands();
|
|
||||||
Preference appEqualizer = findPreference("app_equalizer");
|
|
||||||
if (appEqualizer != null) {
|
|
||||||
appEqualizer.setVisible(numBands > 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void actionAppEqualizer() {
|
|
||||||
Preference appEqualizer = findPreference("app_equalizer");
|
|
||||||
if (appEqualizer != null) {
|
|
||||||
appEqualizer.setOnPreferenceClickListener(preference -> {
|
|
||||||
NavController navController = NavHostFragment.findNavController(this);
|
|
||||||
NavOptions navOptions = new NavOptions.Builder()
|
|
||||||
.setLaunchSingleTop(true)
|
|
||||||
.setPopUpTo(R.id.equalizerFragment, true)
|
|
||||||
.build();
|
|
||||||
activity.setBottomNavigationBarVisibility(true);
|
|
||||||
activity.setBottomSheetVisibility(true);
|
|
||||||
navController.navigate(R.id.equalizerFragment, null, navOptions);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
if (isServiceBound) {
|
|
||||||
requireActivity().unbindService(serviceConnection);
|
|
||||||
isServiceBound = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,112 @@
|
|||||||
|
package com.cappielloantonio.tempo.ui.fragment.bottomsheetdialog;
|
||||||
|
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.media3.common.util.UnstableApi;
|
||||||
|
import androidx.media3.session.MediaBrowser;
|
||||||
|
import androidx.media3.session.SessionToken;
|
||||||
|
|
||||||
|
import com.cappielloantonio.tempo.R;
|
||||||
|
import com.cappielloantonio.tempo.glide.CustomGlideRequest;
|
||||||
|
import com.cappielloantonio.tempo.service.MediaManager;
|
||||||
|
import com.cappielloantonio.tempo.service.MediaService;
|
||||||
|
import com.cappielloantonio.tempo.subsonic.models.PlaylistWithSongs;
|
||||||
|
import com.cappielloantonio.tempo.ui.activity.MainActivity;
|
||||||
|
import com.cappielloantonio.tempo.util.Constants;
|
||||||
|
import com.cappielloantonio.tempo.util.MusicUtil;
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
|
@UnstableApi
|
||||||
|
public class PlaylistBottomSheetDialog extends BottomSheetDialogFragment implements View.OnClickListener {
|
||||||
|
private PlaylistWithSongs playlist;
|
||||||
|
private ListenableFuture<MediaBrowser> mediaBrowserListenableFuture;
|
||||||
|
private static final String TAG = "PlaylistBottomSheetDialog";
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
|
View view = inflater.inflate(R.layout.bottom_sheet_playlist_dialog, container, false);
|
||||||
|
|
||||||
|
playlist = requireArguments().getParcelable(Constants.PLAYLIST_OBJECT);
|
||||||
|
|
||||||
|
init(view);
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||||
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart() {
|
||||||
|
super.onStart();
|
||||||
|
|
||||||
|
initializeMediaBrowser();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStop() {
|
||||||
|
releaseMediaBrowser();
|
||||||
|
super.onStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init(View view) {
|
||||||
|
ImageView coverPlaylist = view.findViewById(R.id.playlist_cover_image_view);
|
||||||
|
|
||||||
|
CustomGlideRequest.Builder
|
||||||
|
.from(view.getContext(), playlist.getCoverArtId(), CustomGlideRequest.ResourceType.Playlist)
|
||||||
|
.build()
|
||||||
|
.into(coverPlaylist);
|
||||||
|
|
||||||
|
TextView titlePlaylist = view.findViewById(R.id.playlist_title_text_view);
|
||||||
|
titlePlaylist.setText(playlist.getName());
|
||||||
|
|
||||||
|
titlePlaylist.setSelected(true);
|
||||||
|
|
||||||
|
TextView countPlaylist = view.findViewById(R.id.playlist_count_text_view);
|
||||||
|
countPlaylist.setText(view.getContext().getString(R.string.playlist_counted_tracks, playlist.getSongCount(), MusicUtil.getReadableDurationString(playlist.getDuration(), false)));
|
||||||
|
|
||||||
|
TextView playNext = view.findViewById(R.id.play_next_text_view);
|
||||||
|
playNext.setOnClickListener(v -> {
|
||||||
|
MediaManager.enqueue(mediaBrowserListenableFuture, playlist.getEntries(), true);
|
||||||
|
((MainActivity) requireActivity()).setBottomSheetInPeek(true);
|
||||||
|
dismissBottomSheet();
|
||||||
|
});
|
||||||
|
|
||||||
|
TextView addToQueue = view.findViewById(R.id.add_to_queue_text_view);
|
||||||
|
addToQueue.setOnClickListener(v -> {
|
||||||
|
MediaManager.enqueue(mediaBrowserListenableFuture, playlist.getEntries(), false);
|
||||||
|
((MainActivity) requireActivity()).setBottomSheetInPeek(true);
|
||||||
|
dismissBottomSheet();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
dismissBottomSheet();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dismissBottomSheet() {
|
||||||
|
dismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeMediaBrowser() {
|
||||||
|
mediaBrowserListenableFuture = new MediaBrowser.Builder(requireContext(), new SessionToken(requireContext(), new ComponentName(requireContext(), MediaService.class))).buildAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void releaseMediaBrowser() {
|
||||||
|
MediaBrowser.releaseFuture(mediaBrowserListenableFuture);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -92,6 +92,7 @@ object Preferences {
|
|||||||
private const val ARTIST_DISPLAY_BIOGRAPHY= "artist_display_biography"
|
private const val ARTIST_DISPLAY_BIOGRAPHY= "artist_display_biography"
|
||||||
private const val NETWORK_PING_TIMEOUT = "network_ping_timeout_base"
|
private const val NETWORK_PING_TIMEOUT = "network_ping_timeout_base"
|
||||||
|
|
||||||
|
private const val TILE_SIZE = "tile_size"
|
||||||
private const val AA_ALBUM_VIEW = "androidauto_album_view"
|
private const val AA_ALBUM_VIEW = "androidauto_album_view"
|
||||||
private const val AA_HOME_VIEW = "androidauto_home_view"
|
private const val AA_HOME_VIEW = "androidauto_home_view"
|
||||||
private const val AA_PLAYLIST_VIEW = "androidauto_playlist_view"
|
private const val AA_PLAYLIST_VIEW = "androidauto_playlist_view"
|
||||||
@@ -101,6 +102,7 @@ object Preferences {
|
|||||||
private const val AA_SECOND_TAB = "androidauto_second_tab"
|
private const val AA_SECOND_TAB = "androidauto_second_tab"
|
||||||
private const val AA_THIRD_TAB = "androidauto_third_tab"
|
private const val AA_THIRD_TAB = "androidauto_third_tab"
|
||||||
private const val AA_FOURTH_TAB = "androidauto_fourth_tab"
|
private const val AA_FOURTH_TAB = "androidauto_fourth_tab"
|
||||||
|
private const val AA_SHUFFLE_GENRE_SONGS = "androidauto_shuffle_genre_songs"
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getServer(): String? {
|
fun getServer(): String? {
|
||||||
@@ -769,6 +771,10 @@ object Preferences {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
fun getTileSize(): Int {
|
||||||
|
val parsed = App.getInstance().preferences.getString(TILE_SIZE, "2")?.toIntOrNull()
|
||||||
|
return parsed?.takeIf { it in 2..6 } ?: 2
|
||||||
|
}
|
||||||
fun isAndroidAutoAlbumViewEnabled(): Boolean {
|
fun isAndroidAutoAlbumViewEnabled(): Boolean {
|
||||||
return App.getInstance().preferences.getBoolean(AA_ALBUM_VIEW, true)
|
return App.getInstance().preferences.getBoolean(AA_ALBUM_VIEW, true)
|
||||||
}
|
}
|
||||||
@@ -813,4 +819,14 @@ object Preferences {
|
|||||||
return App.getInstance().preferences.getString(AA_FOURTH_TAB, "3")!!.toInt()
|
return App.getInstance().preferences.getString(AA_FOURTH_TAB, "3")!!.toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun isAndroidAutoShuffleGenreSongsEnabled(): Boolean {
|
||||||
|
return App.getInstance().preferences.getBoolean(AA_SHUFFLE_GENRE_SONGS, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun setAndroidAutoShuffleGenreSongsEnabled(enabled: Boolean) {
|
||||||
|
App.getInstance().preferences.edit().putBoolean(AA_SHUFFLE_GENRE_SONGS, enabled).apply()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
package com.cappielloantonio.tempo.util;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.DisplayMetrics;
|
||||||
|
|
||||||
|
public class TileSizeManager {
|
||||||
|
|
||||||
|
private static TileSizeManager instance;
|
||||||
|
|
||||||
|
private int tileSizePx;
|
||||||
|
private int tileSpanCount;
|
||||||
|
private int tileSpacing;
|
||||||
|
private int genreSizePx;
|
||||||
|
private int genreSpanCount;
|
||||||
|
private int genreSpacing;
|
||||||
|
private int GenreSpacing;
|
||||||
|
private int discoverWidthPx;
|
||||||
|
private int discoverHeightPx;
|
||||||
|
private boolean tileIsInitialized;
|
||||||
|
private boolean genreIsInitialized;
|
||||||
|
private boolean discoverIsInitialized;
|
||||||
|
|
||||||
|
private TileSizeManager() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TileSizeManager getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new TileSizeManager();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTileSizePx(Context context) {
|
||||||
|
if( !tileIsInitialized )
|
||||||
|
calculateTileSize(context);
|
||||||
|
return tileSizePx;
|
||||||
|
}
|
||||||
|
public int getTileSpanCount(Context context) {
|
||||||
|
if( !tileIsInitialized )
|
||||||
|
calculateTileSize(context);
|
||||||
|
return tileSpanCount;
|
||||||
|
}
|
||||||
|
public int getTileSpacing(Context context) {
|
||||||
|
if( !tileIsInitialized )
|
||||||
|
calculateTileSize(context);
|
||||||
|
return tileSpacing;
|
||||||
|
}
|
||||||
|
public int getGenreSizePx(Context context) {
|
||||||
|
if( !genreIsInitialized )
|
||||||
|
calculateGenreSize(context);
|
||||||
|
return genreSizePx;
|
||||||
|
}
|
||||||
|
public int getGenreSpanCount(Context context) {
|
||||||
|
if( !genreIsInitialized )
|
||||||
|
calculateGenreSize(context);
|
||||||
|
return genreSpanCount;
|
||||||
|
}
|
||||||
|
public int getGenreSpacing(Context context) {
|
||||||
|
if( !genreIsInitialized )
|
||||||
|
calculateGenreSize(context);
|
||||||
|
return genreSpacing;
|
||||||
|
}
|
||||||
|
public int getDiscoverWidthPx(Context context) {
|
||||||
|
if( !discoverIsInitialized )
|
||||||
|
calculateTileSize(context);
|
||||||
|
return discoverWidthPx;
|
||||||
|
}
|
||||||
|
public int getDiscoverHeightPx(Context context) {
|
||||||
|
if( !discoverIsInitialized )
|
||||||
|
calculateTileSize(context);
|
||||||
|
return discoverHeightPx;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void calculateTileSize(Context context) {
|
||||||
|
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
|
||||||
|
float screenWidth = metrics.widthPixels;
|
||||||
|
float screenHeight = metrics.heightPixels;
|
||||||
|
|
||||||
|
// retrieve the divisor in the preferences
|
||||||
|
int userTileSize = Math.max(2, Math.min(6, Preferences.getTileSize()));
|
||||||
|
float divisor = (float)userTileSize;
|
||||||
|
|
||||||
|
// little pading = 10
|
||||||
|
tileSizePx = Math.round(Math.min(screenWidth, screenHeight) / divisor) - 10;
|
||||||
|
tileSpanCount = Math.max(2, Math.round(screenWidth / (float)tileSizePx) );
|
||||||
|
|
||||||
|
switch (userTileSize) {
|
||||||
|
default:
|
||||||
|
case 2: // XL
|
||||||
|
tileSpacing = 20;
|
||||||
|
break;
|
||||||
|
case 3: // L
|
||||||
|
tileSpacing = 15;
|
||||||
|
break;
|
||||||
|
case 4: // M
|
||||||
|
tileSpacing = 10;
|
||||||
|
break;
|
||||||
|
case 5: // S
|
||||||
|
tileSpacing = 6;
|
||||||
|
break;
|
||||||
|
case 6: // SX
|
||||||
|
tileSpacing = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tileIsInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void calculateGenreSize(Context context) {
|
||||||
|
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
|
||||||
|
float screenWidth = metrics.widthPixels;
|
||||||
|
float screenHeight = metrics.heightPixels;
|
||||||
|
|
||||||
|
// retrieve the divisor in the preferences
|
||||||
|
int userTileSize = Math.max(2, Math.min(3, Preferences.getTileSize()));
|
||||||
|
float divisor = (float)userTileSize;
|
||||||
|
|
||||||
|
// little pading = 10
|
||||||
|
genreSizePx = Math.round(Math.min(screenWidth, screenHeight) / divisor) - 10;
|
||||||
|
genreSpanCount = Math.max(2, Math.round(screenWidth / (float)genreSizePx) );
|
||||||
|
|
||||||
|
switch (userTileSize) {
|
||||||
|
default:
|
||||||
|
case 2: // XL
|
||||||
|
genreSpacing = 20;
|
||||||
|
break;
|
||||||
|
case 3: // L
|
||||||
|
genreSpacing = 15;
|
||||||
|
break;
|
||||||
|
case 4: // M
|
||||||
|
genreSpacing = 10;
|
||||||
|
break;
|
||||||
|
case 5: // S
|
||||||
|
genreSpacing = 6;
|
||||||
|
break;
|
||||||
|
case 6: // XS
|
||||||
|
genreSpacing = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
genreIsInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void calculateDiscoverSize(Context context) {
|
||||||
|
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
|
||||||
|
float screenWidth = metrics.widthPixels;
|
||||||
|
float screenHeight = metrics.heightPixels;
|
||||||
|
float discoverDivisor;
|
||||||
|
|
||||||
|
// retrieve the divisor in the preferences
|
||||||
|
int userTileSize = Math.max(2, Math.min(6, Preferences.getTileSize()));
|
||||||
|
|
||||||
|
switch (userTileSize) {
|
||||||
|
default:
|
||||||
|
case 2: // XL
|
||||||
|
discoverDivisor = 1.0f;
|
||||||
|
break;
|
||||||
|
case 3: // L
|
||||||
|
discoverDivisor = 1.25f;
|
||||||
|
break;
|
||||||
|
case 4: // M
|
||||||
|
discoverDivisor = 1.5f;
|
||||||
|
break;
|
||||||
|
case 5: // S
|
||||||
|
discoverDivisor = 1.75f;
|
||||||
|
break;
|
||||||
|
case 6: // XS
|
||||||
|
discoverDivisor = 2.0f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
discoverWidthPx = Math.round(Math.min(screenWidth, screenHeight) / discoverDivisor) - 50;
|
||||||
|
discoverHeightPx = Math.round((float)discoverWidthPx * 0.6f);
|
||||||
|
discoverIsInitialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,11 +5,13 @@ import android.app.Application;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.lifecycle.AndroidViewModel;
|
import androidx.lifecycle.AndroidViewModel;
|
||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.media3.common.util.UnstableApi;
|
||||||
|
|
||||||
import com.cappielloantonio.tempo.model.RecentSearch;
|
import com.cappielloantonio.tempo.model.RecentSearch;
|
||||||
import com.cappielloantonio.tempo.repository.SearchingRepository;
|
import com.cappielloantonio.tempo.repository.SearchingRepository;
|
||||||
import com.cappielloantonio.tempo.subsonic.models.SearchResult2;
|
import com.cappielloantonio.tempo.subsonic.models.SearchResult2;
|
||||||
import com.cappielloantonio.tempo.subsonic.models.SearchResult3;
|
import com.cappielloantonio.tempo.subsonic.models.SearchResult3;
|
||||||
|
import com.cappielloantonio.tempo.ui.fragment.SearchFragment;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -43,8 +45,9 @@ public class SearchViewModel extends AndroidViewModel {
|
|||||||
return searchingRepository.search2(title);
|
return searchingRepository.search2(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<SearchResult3> search3(String title) {
|
@UnstableApi
|
||||||
return searchingRepository.search3(title);
|
public LiveData<SearchResult3> search3(SearchFragment sf, String title) {
|
||||||
|
return searchingRepository.search3(sf, title);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void insertNewSearch(String search) {
|
public void insertNewSearch(String search) {
|
||||||
|
|||||||
11
app/src/main/res/drawable/ic_aa_genres.xml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:width="24dp">
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M480,660Q555,660 607.5,607.5Q660,555 660,480Q660,405 607.5,352.5Q555,300 480,300Q405,300 352.5,352.5Q300,405 300,480Q300,555 352.5,607.5Q405,660 480,660ZM480,880Q397,880 324,848.5Q251,817 197,763Q143,709 111.5,636Q80,563 80,480Q80,397 111.5,324Q143,251 197,197Q251,143 324,111.5Q397,80 480,80Q563,80 636,111.5Q709,143 763,197Q817,251 848.5,324Q880,397 880,480Q880,563 848.5,636Q817,709 763,763Q709,817 636,848.5Q563,880 480,880Z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
10
app/src/main/res/drawable/ic_launcher_background.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
|
android:viewportWidth="108"
|
||||||
|
android:viewportHeight="108">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFEC4A4A"
|
||||||
|
android:pathData="M0,0h108v108h-108z" />
|
||||||
|
</vector>
|
||||||
@@ -1,56 +1,77 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:aapt="http://schemas.android.com/aapt"
|
||||||
android:width="108dp"
|
android:width="108dp"
|
||||||
android:height="108dp"
|
android:height="108dp"
|
||||||
android:viewportWidth="512"
|
android:viewportWidth="108"
|
||||||
android:viewportHeight="512">
|
android:viewportHeight="108">
|
||||||
<group android:scaleX="0.49"
|
|
||||||
android:scaleY="0.49"
|
<group
|
||||||
android:translateX="130.56"
|
android:scaleX="0.13"
|
||||||
android:translateY="130.56">
|
android:scaleY="0.13"
|
||||||
<path
|
android:translateX="21.5"
|
||||||
android:pathData="M512,437.33c0,11.78 -9.56,21.34 -21.34,21.34H21.33C9.55,458.67 0,449.11 0,437.33V96c0,-11.78 9.55,-21.33 21.33,-21.33h469.33c11.78,0 21.34,9.55 21.34,21.33L512,437.33L512,437.33z"
|
android:translateY="21.5">
|
||||||
android:fillColor="#DA4453"/>
|
<path
|
||||||
<path
|
android:pathData="M250,0c138.07,0 250,111.93 250,250S388.07,500 250,500 0,388.07 0,250 111.93,0 250,0ZM250,235c-8.28,0 -15,6.72 -15,15c0,8.28 6.72,15 15,15c8.28,0 15,-6.72 15,-15c0,-8.28 -6.72,-15 -15,-15Z">
|
||||||
android:pathData="M512,416.01c0,11.78 -9.56,21.31 -21.34,21.31H21.33C9.55,437.33 0,427.8 0,416.01V74.67c0,-11.78 9.55,-21.34 21.33,-21.34h469.33c11.78,0 21.34,9.56 21.34,21.34L512,416.01L512,416.01z"
|
<aapt:attr name="android:fillColor">
|
||||||
android:fillColor="#ED5564"/>
|
<gradient
|
||||||
<path
|
android:startX="122.34"
|
||||||
android:pathData="M63.99,160c-5.89,0 -10.66,4.78 -10.66,10.67v149.34c0,5.88 4.77,10.66 10.66,10.66c5.89,0 10.67,-4.78 10.67,-10.66V170.67C74.66,164.78 69.88,160 63.99,160z"
|
android:startY="23.55"
|
||||||
android:fillColor="#DA4453"/>
|
android:endX="377.69"
|
||||||
<path
|
android:endY="465.83"
|
||||||
android:pathData="M74.66,106.67c0,5.89 -4.78,10.66 -10.67,10.66c-5.89,0 -10.66,-4.77 -10.66,-10.66S58.1,96 63.99,96C69.88,96 74.66,100.78 74.66,106.67z"
|
android:type="linear">
|
||||||
android:fillColor="#E6E9ED"/>
|
<item android:offset="0.0" android:color="#FFEC4A4A" />
|
||||||
<path
|
<item android:offset="1.0" android:color="#FFEC4A4A" />
|
||||||
android:pathData="M74.66,384.01c0,5.88 -4.78,10.66 -10.67,10.66c-5.89,0 -10.66,-4.78 -10.66,-10.66c0,-5.91 4.77,-10.69 10.66,-10.69C69.88,373.33 74.66,378.11 74.66,384.01z"
|
</gradient>
|
||||||
android:fillColor="#E6E9ED"/>
|
</aapt:attr>
|
||||||
<path
|
</path>
|
||||||
android:pathData="M448,123.73h-21.34v203.19l-40.31,50.41v0.02c-1.47,1.83 -2.34,4.14 -2.34,6.67c0,5.88 4.78,10.66 10.66,10.66c3.38,0 6.38,-1.56 8.33,-4h0.02l42.66,-53.34l0,0c1.47,-1.81 2.34,-4.13 2.34,-6.66V123.73z"
|
|
||||||
android:fillColor="#E6E9ED"/>
|
<path
|
||||||
<path
|
android:pathData="M250.41,20.5c126.89,0 229.75,102.86 229.75,229.75c0,126.89 -102.86,229.75 -229.75,229.75c-126.89,0 -229.75,-102.86 -229.75,-229.75C20.66,123.36 123.53,20.5 250.41,20.5ZM250.85,161.82c-49.09,0 -88.88,39.79 -88.88,88.88c0,49.09 39.79,88.88 88.88,88.88c49.09,0 88.88,-39.79 88.88,-88.88c0,-49.09 -39.79,-88.88 -88.88,-88.88Z">
|
||||||
android:pathData="M437.33,149.33c-11.77,0 -21.33,-9.56 -21.33,-21.33s9.56,-21.33 21.33,-21.33s21.33,9.56 21.33,21.33S449.09,149.33 437.33,149.33z"
|
<aapt:attr name="android:fillColor">
|
||||||
android:fillColor="#E6E9ED"/>
|
<gradient
|
||||||
<path
|
android:startX="116.21"
|
||||||
android:pathData="M437.33,96c-17.67,0 -32,14.33 -32,32s14.33,32 32,32s32,-14.33 32,-32S455,96 437.33,96zM437.33,138.67c-5.89,0 -10.67,-4.8 -10.67,-10.67c0,-5.88 4.78,-10.67 10.67,-10.67s10.67,4.8 10.67,10.67C448,133.88 443.22,138.67 437.33,138.67z"
|
android:startY="67.61"
|
||||||
android:fillColor="#CCD1D9"/>
|
android:endX="403.29"
|
||||||
<path
|
android:endY="429.34"
|
||||||
android:pathData="M405.33,245.33c0,82.48 -66.86,149.34 -149.33,149.34c-82.47,0 -149.33,-66.86 -149.33,-149.34C106.66,162.86 173.52,96 255.99,96C338.47,96 405.33,162.86 405.33,245.33z"
|
android:type="linear">
|
||||||
android:fillColor="#434A54"/>
|
<item android:offset="0.0" android:color="#66060606" />
|
||||||
<path
|
<item android:offset="1.0" android:color="#CC060606" />
|
||||||
android:pathData="M266.66,149.33c0,-5.89 -4.77,-10.66 -10.67,-10.66c-58.91,0 -106.66,47.75 -106.66,106.65l0,0c0,5.89 4.77,10.67 10.66,10.67s10.67,-4.78 10.67,-10.67l0,0c0,-22.78 8.88,-44.22 24.99,-60.33c16.12,-16.13 37.55,-25 60.34,-25C261.89,160 266.66,155.22 266.66,149.33z"
|
</gradient>
|
||||||
android:fillColor="#656D78"/>
|
</aapt:attr>
|
||||||
<path
|
</path>
|
||||||
android:pathData="M352,234.67c-5.9,0 -10.67,4.77 -10.67,10.66l0,0c0,22.8 -8.88,44.23 -24.98,60.34c-16.13,16.13 -37.56,25 -60.35,25c-5.89,0 -10.66,4.78 -10.66,10.66c0,5.91 4.77,10.69 10.66,10.69c58.91,0 106.66,-47.77 106.66,-106.69C362.65,239.44 357.89,234.67 352,234.67z"
|
|
||||||
android:fillColor="#656D78"/>
|
<path
|
||||||
<path
|
android:pathData="M453.23,307.8c-18.5,72.24 -73.8,129.26 -144.2,148.92l-36.39,-138.74c21.97,-7.21 39.22,-24.84 45.88,-47.06l134.71,36.88Z">
|
||||||
android:pathData="M255.99,288.01c-23.52,0 -42.66,-19.16 -42.66,-42.69c0,-23.52 19.14,-42.66 42.66,-42.66c23.54,0 42.66,19.14 42.66,42.66C298.65,268.86 279.53,288.01 255.99,288.01z"
|
<aapt:attr name="android:fillColor">
|
||||||
android:fillColor="#FFCE54"/>
|
<gradient
|
||||||
<path
|
android:startX="420.63"
|
||||||
android:pathData="M255.99,192c-29.45,0 -53.33,23.88 -53.33,53.33s23.88,53.34 53.33,53.34c29.46,0 53.34,-23.89 53.34,-53.34S285.45,192 255.99,192zM255.99,277.34c-17.64,0 -32,-14.36 -32,-32.02c0,-17.64 14.36,-32 32,-32c17.65,0 32.01,14.36 32.01,32C288,262.98 273.64,277.34 255.99,277.34z"
|
android:startY="403.74"
|
||||||
android:fillColor="#F6BB42"/>
|
android:endX="78.4"
|
||||||
<path
|
android:endY="117.92"
|
||||||
android:pathData="M266.66,245.33c0,5.89 -4.77,10.67 -10.67,10.67c-5.89,0 -10.66,-4.78 -10.66,-10.67s4.77,-10.66 10.66,-10.66C261.89,234.67 266.66,239.44 266.66,245.33z"
|
android:type="linear">
|
||||||
android:fillColor="#434A54"/>
|
<item android:offset="0.0" android:color="#33FFFFFF" />
|
||||||
<path
|
<item android:offset="1.0" android:color="#4DFFFFFF" />
|
||||||
android:pathData="M74.66,234.67H53.33c-5.89,0 -10.66,4.77 -10.66,10.66s4.77,10.67 10.66,10.67h21.34c5.89,0 10.66,-4.78 10.66,-10.67S80.56,234.67 74.66,234.67z"
|
</gradient>
|
||||||
android:fillColor="#434A54"/>
|
</aapt:attr>
|
||||||
</group>
|
</path>
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:pathData="M228.3,183.04c-21.73,7.15 -38.82,24.5 -45.62,46.39L47.5,192.42c18.5,-72.24 73.8,-129.26 144.2,-148.92l36.6,139.54Z">
|
||||||
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:startX="420.63"
|
||||||
|
android:startY="403.74"
|
||||||
|
android:endX="78.4"
|
||||||
|
android:endY="117.92"
|
||||||
|
android:type="linear">
|
||||||
|
<item android:offset="0.0" android:color="#33FFFFFF" />
|
||||||
|
<item android:offset="1.0" android:color="#4DFFFFFF" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:fillColor="#66FFFFFF"
|
||||||
|
android:pathData="M250.5,179.5c39.21,0 71,31.79 71,71s-31.79,71 -71,71s-71,-31.79 -71,-71s31.79,-71 71,-71ZM250,235c-8.28,0 -15,6.72 -15,15c0,8.28 6.72,15 15,15c8.28,0 15,-6.72 15,-15c0,-8.28 -6.72,-15 -15,-15Z" />
|
||||||
|
</group>
|
||||||
</vector>
|
</vector>
|
||||||
27
app/src/main/res/drawable/ic_launcher_monochrome.xml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
|
android:viewportWidth="108"
|
||||||
|
android:viewportHeight="108">
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:fillColor="#424940"
|
||||||
|
android:pathData="M54,50.6018C55.8768,50.6018 57.3982,52.1232 57.3982,54C57.3982,55.8768 55.8768,57.3982 54,57.3982C52.1232,57.3982 50.6018,55.8768 50.6018,54C50.6018,52.1232 52.1232,50.6018 54,50.6018Z"/>
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:fillColor="#424940"
|
||||||
|
android:pathData="M54.1049,42.2712C60.6295,42.2712 65.9187,47.5605 65.9188,54.0851C65.9188,60.6097 60.6295,65.8989 54.1049,65.8989C47.5802,65.8989 42.2907,60.6097 42.2907,54.0851C42.2908,47.5604 47.5802,42.2712 54.1049,42.2712ZM54.0611,46.3408C49.7973,46.3408 46.3408,49.7973 46.3408,54.0611C46.3408,58.3249 49.7972,61.7815 54.0611,61.7816C58.3249,61.7816 61.7816,58.3249 61.7816,54.0611C61.7815,49.7972 58.3249,46.3408 54.0611,46.3408Z"/>
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:fillColor="#424940"
|
||||||
|
android:pathData="M54,22.5C71.397,22.5 85.5,36.603 85.5,54C85.5,71.397 71.397,85.5 54,85.5C36.603,85.5 22.5,71.397 22.5,54C22.5,36.603 36.603,22.5 54,22.5ZM54.0506,26.9138C39.0743,26.9138 26.9334,39.0545 26.9334,54.0308C26.9334,69.007 39.0743,81.1477 54.0506,81.1477C69.0268,81.1476 81.1675,69.007 81.1675,54.0308C81.1675,39.0545 69.0268,26.9139 54.0506,26.9138Z"/>
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:fillColor="#424940"
|
||||||
|
android:pathData="M43.4405,31.2951C43.9287,31.1317 44.4432,31.4282 44.5738,31.9262L46.9248,40.8911C47.055,41.3873 46.8662,41.9097 46.4665,42.2312C44.8479,43.5335 43.4426,45.0999 42.3131,46.8671C42.0058,47.3479 41.4269,47.5914 40.8765,47.4408L31.9176,44.9882C31.4322,44.8554 31.141,44.3566 31.2884,43.8754C33.1082,37.9357 37.6601,33.2302 43.4405,31.2951Z"/>
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:fillColor="#424940"
|
||||||
|
android:pathData="M65.1611,75.9356C64.6879,76.0939 64.1895,75.8064 64.0629,75.3238L61.7908,66.6599C61.6607,66.1637 61.8495,65.6414 62.2488,65.3193C63.8012,64.0666 65.1506,62.5627 66.2378,60.8676C66.5459,60.3873 67.1247,60.1437 67.675,60.2943L76.3298,62.6636C76.8002,62.7924 77.0825,63.2759 76.9397,63.7422C75.1759,69.4992 70.7637,74.0601 65.1611,75.9356Z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
@@ -1,56 +1,77 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:aapt="http://schemas.android.com/aapt"
|
||||||
android:width="108dp"
|
android:width="108dp"
|
||||||
android:height="108dp"
|
android:height="108dp"
|
||||||
android:viewportWidth="512"
|
android:viewportWidth="108"
|
||||||
android:viewportHeight="512">
|
android:viewportHeight="108">
|
||||||
<group android:scaleX="0.55"
|
|
||||||
android:scaleY="0.55"
|
<group
|
||||||
android:translateX="150.56"
|
android:scaleX="0.13"
|
||||||
android:translateY="150.56">
|
android:scaleY="0.13"
|
||||||
<path
|
android:translateX="21.5"
|
||||||
android:pathData="M512,437.33c0,11.78 -9.56,21.34 -21.34,21.34H21.33C9.55,458.67 0,449.11 0,437.33V96c0,-11.78 9.55,-21.33 21.33,-21.33h469.33c11.78,0 21.34,9.55 21.34,21.33L512,437.33L512,437.33z"
|
android:translateY="21.5">
|
||||||
android:fillColor="#DA4453"/>
|
<path
|
||||||
<path
|
android:pathData="M250,0c138.07,0 250,111.93 250,250S388.07,500 250,500 0,388.07 0,250 111.93,0 250,0ZM250,235c-8.28,0 -15,6.72 -15,15c0,8.28 6.72,15 15,15c8.28,0 15,-6.72 15,-15c0,-8.28 -6.72,-15 -15,-15Z">
|
||||||
android:pathData="M512,416.01c0,11.78 -9.56,21.31 -21.34,21.31H21.33C9.55,437.33 0,427.8 0,416.01V74.67c0,-11.78 9.55,-21.34 21.33,-21.34h469.33c11.78,0 21.34,9.56 21.34,21.34L512,416.01L512,416.01z"
|
<aapt:attr name="android:fillColor">
|
||||||
android:fillColor="#ED5564"/>
|
<gradient
|
||||||
<path
|
android:startX="122.34"
|
||||||
android:pathData="M63.99,160c-5.89,0 -10.66,4.78 -10.66,10.67v149.34c0,5.88 4.77,10.66 10.66,10.66c5.89,0 10.67,-4.78 10.67,-10.66V170.67C74.66,164.78 69.88,160 63.99,160z"
|
android:startY="23.55"
|
||||||
android:fillColor="#DA4453"/>
|
android:endX="377.69"
|
||||||
<path
|
android:endY="465.83"
|
||||||
android:pathData="M74.66,106.67c0,5.89 -4.78,10.66 -10.67,10.66c-5.89,0 -10.66,-4.77 -10.66,-10.66S58.1,96 63.99,96C69.88,96 74.66,100.78 74.66,106.67z"
|
android:type="linear">
|
||||||
android:fillColor="#E6E9ED"/>
|
<item android:offset="0.0" android:color="#FFEC4A4A" />
|
||||||
<path
|
<item android:offset="1.0" android:color="#FFEC4A4A" />
|
||||||
android:pathData="M74.66,384.01c0,5.88 -4.78,10.66 -10.67,10.66c-5.89,0 -10.66,-4.78 -10.66,-10.66c0,-5.91 4.77,-10.69 10.66,-10.69C69.88,373.33 74.66,378.11 74.66,384.01z"
|
</gradient>
|
||||||
android:fillColor="#E6E9ED"/>
|
</aapt:attr>
|
||||||
<path
|
</path>
|
||||||
android:pathData="M448,123.73h-21.34v203.19l-40.31,50.41v0.02c-1.47,1.83 -2.34,4.14 -2.34,6.67c0,5.88 4.78,10.66 10.66,10.66c3.38,0 6.38,-1.56 8.33,-4h0.02l42.66,-53.34l0,0c1.47,-1.81 2.34,-4.13 2.34,-6.66V123.73z"
|
|
||||||
android:fillColor="#E6E9ED"/>
|
<path
|
||||||
<path
|
android:pathData="M250.41,20.5c126.89,0 229.75,102.86 229.75,229.75c0,126.89 -102.86,229.75 -229.75,229.75c-126.89,0 -229.75,-102.86 -229.75,-229.75C20.66,123.36 123.53,20.5 250.41,20.5ZM250.85,161.82c-49.09,0 -88.88,39.79 -88.88,88.88c0,49.09 39.79,88.88 88.88,88.88c49.09,0 88.88,-39.79 88.88,-88.88c0,-49.09 -39.79,-88.88 -88.88,-88.88Z">
|
||||||
android:pathData="M437.33,149.33c-11.77,0 -21.33,-9.56 -21.33,-21.33s9.56,-21.33 21.33,-21.33s21.33,9.56 21.33,21.33S449.09,149.33 437.33,149.33z"
|
<aapt:attr name="android:fillColor">
|
||||||
android:fillColor="#E6E9ED"/>
|
<gradient
|
||||||
<path
|
android:startX="116.21"
|
||||||
android:pathData="M437.33,96c-17.67,0 -32,14.33 -32,32s14.33,32 32,32s32,-14.33 32,-32S455,96 437.33,96zM437.33,138.67c-5.89,0 -10.67,-4.8 -10.67,-10.67c0,-5.88 4.78,-10.67 10.67,-10.67s10.67,4.8 10.67,10.67C448,133.88 443.22,138.67 437.33,138.67z"
|
android:startY="67.61"
|
||||||
android:fillColor="#CCD1D9"/>
|
android:endX="403.29"
|
||||||
<path
|
android:endY="429.34"
|
||||||
android:pathData="M405.33,245.33c0,82.48 -66.86,149.34 -149.33,149.34c-82.47,0 -149.33,-66.86 -149.33,-149.34C106.66,162.86 173.52,96 255.99,96C338.47,96 405.33,162.86 405.33,245.33z"
|
android:type="linear">
|
||||||
android:fillColor="#434A54"/>
|
<item android:offset="0.0" android:color="#66060606" />
|
||||||
<path
|
<item android:offset="1.0" android:color="#CC060606" />
|
||||||
android:pathData="M266.66,149.33c0,-5.89 -4.77,-10.66 -10.67,-10.66c-58.91,0 -106.66,47.75 -106.66,106.65l0,0c0,5.89 4.77,10.67 10.66,10.67s10.67,-4.78 10.67,-10.67l0,0c0,-22.78 8.88,-44.22 24.99,-60.33c16.12,-16.13 37.55,-25 60.34,-25C261.89,160 266.66,155.22 266.66,149.33z"
|
</gradient>
|
||||||
android:fillColor="#656D78"/>
|
</aapt:attr>
|
||||||
<path
|
</path>
|
||||||
android:pathData="M352,234.67c-5.9,0 -10.67,4.77 -10.67,10.66l0,0c0,22.8 -8.88,44.23 -24.98,60.34c-16.13,16.13 -37.56,25 -60.35,25c-5.89,0 -10.66,4.78 -10.66,10.66c0,5.91 4.77,10.69 10.66,10.69c58.91,0 106.66,-47.77 106.66,-106.69C362.65,239.44 357.89,234.67 352,234.67z"
|
|
||||||
android:fillColor="#656D78"/>
|
<path
|
||||||
<path
|
android:pathData="M453.23,307.8c-18.5,72.24 -73.8,129.26 -144.2,148.92l-36.39,-138.74c21.97,-7.21 39.22,-24.84 45.88,-47.06l134.71,36.88Z">
|
||||||
android:pathData="M255.99,288.01c-23.52,0 -42.66,-19.16 -42.66,-42.69c0,-23.52 19.14,-42.66 42.66,-42.66c23.54,0 42.66,19.14 42.66,42.66C298.65,268.86 279.53,288.01 255.99,288.01z"
|
<aapt:attr name="android:fillColor">
|
||||||
android:fillColor="#FFCE54"/>
|
<gradient
|
||||||
<path
|
android:startX="420.63"
|
||||||
android:pathData="M255.99,192c-29.45,0 -53.33,23.88 -53.33,53.33s23.88,53.34 53.33,53.34c29.46,0 53.34,-23.89 53.34,-53.34S285.45,192 255.99,192zM255.99,277.34c-17.64,0 -32,-14.36 -32,-32.02c0,-17.64 14.36,-32 32,-32c17.65,0 32.01,14.36 32.01,32C288,262.98 273.64,277.34 255.99,277.34z"
|
android:startY="403.74"
|
||||||
android:fillColor="#F6BB42"/>
|
android:endX="78.4"
|
||||||
<path
|
android:endY="117.92"
|
||||||
android:pathData="M266.66,245.33c0,5.89 -4.77,10.67 -10.67,10.67c-5.89,0 -10.66,-4.78 -10.66,-10.67s4.77,-10.66 10.66,-10.66C261.89,234.67 266.66,239.44 266.66,245.33z"
|
android:type="linear">
|
||||||
android:fillColor="#434A54"/>
|
<item android:offset="0.0" android:color="#33FFFFFF" />
|
||||||
<path
|
<item android:offset="1.0" android:color="#4DFFFFFF" />
|
||||||
android:pathData="M74.66,234.67H53.33c-5.89,0 -10.66,4.77 -10.66,10.66s4.77,10.67 10.66,10.67h21.34c5.89,0 10.66,-4.78 10.66,-10.67S80.56,234.67 74.66,234.67z"
|
</gradient>
|
||||||
android:fillColor="#434A54"/>
|
</aapt:attr>
|
||||||
</group>
|
</path>
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:pathData="M228.3,183.04c-21.73,7.15 -38.82,24.5 -45.62,46.39L47.5,192.42c18.5,-72.24 73.8,-129.26 144.2,-148.92l36.6,139.54Z">
|
||||||
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:startX="420.63"
|
||||||
|
android:startY="403.74"
|
||||||
|
android:endX="78.4"
|
||||||
|
android:endY="117.92"
|
||||||
|
android:type="linear">
|
||||||
|
<item android:offset="0.0" android:color="#33FFFFFF" />
|
||||||
|
<item android:offset="1.0" android:color="#4DFFFFFF" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:fillColor="#66FFFFFF"
|
||||||
|
android:pathData="M250.5,179.5c39.21,0 71,31.79 71,71s-31.79,71 -71,71s-71,-31.79 -71,-71s31.79,-71 71,-71ZM250,235c-8.28,0 -15,6.72 -15,15c0,8.28 6.72,15 15,15c8.28,0 15,-6.72 15,-15c0,-8.28 -6.72,-15 -15,-15Z" />
|
||||||
|
</group>
|
||||||
</vector>
|
</vector>
|
||||||
@@ -1,52 +1,77 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="24dp"
|
xmlns:aapt="http://schemas.android.com/aapt"
|
||||||
android:height="24dp"
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
android:viewportWidth="512"
|
android:viewportWidth="512"
|
||||||
android:viewportHeight="512">
|
android:viewportHeight="522">
|
||||||
|
<group
|
||||||
|
android:scaleX="1.0"
|
||||||
|
android:scaleY="1.0"
|
||||||
|
android:translateX="14.0"
|
||||||
|
android:translateY="14.0">
|
||||||
|
|
||||||
<path
|
<path
|
||||||
android:pathData="M512,437.33c0,11.78 -9.56,21.34 -21.34,21.34H21.33C9.55,458.67 0,449.11 0,437.33V96c0,-11.78 9.55,-21.33 21.33,-21.33h469.33c11.78,0 21.34,9.55 21.34,21.33L512,437.33L512,437.33z"
|
android:pathData="M250,0c138.07,0 250,111.93 250,250S388.07,500 250,500 0,388.07 0,250 111.93,0 250,0ZM250,235c-8.28,0 -15,6.72 -15,15c0,8.28 6.72,15 15,15c8.28,0 15,-6.72 15,-15c0,-8.28 -6.72,-15 -15,-15Z">
|
||||||
android:fillColor="#DA4453"/>
|
<aapt:attr name="android:fillColor">
|
||||||
<path
|
<gradient
|
||||||
android:pathData="M512,416.01c0,11.78 -9.56,21.31 -21.34,21.31H21.33C9.55,437.33 0,427.8 0,416.01V74.67c0,-11.78 9.55,-21.34 21.33,-21.34h469.33c11.78,0 21.34,9.56 21.34,21.34L512,416.01L512,416.01z"
|
android:startX="122.34"
|
||||||
android:fillColor="#ED5564"/>
|
android:startY="23.55"
|
||||||
|
android:endX="377.69"
|
||||||
|
android:endY="465.83"
|
||||||
|
android:type="linear">
|
||||||
|
<item android:offset="0.0" android:color="#FFEC4A4A" />
|
||||||
|
<item android:offset="1.0" android:color="#FFEC4A4A" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
|
||||||
<path android:pathData="M63.99,160c-5.89,0 -10.66,4.78 -10.66,10.67v149.34c0,5.88 4.77,10.66 10.66,10.66c5.89,0 10.67,-4.78 10.67,-10.66V170.67C74.66,164.78 69.88,160 63.99,160z"
|
<path
|
||||||
android:fillColor="#DA4453"/>
|
android:pathData="M250.41,20.5c126.89,0 229.75,102.86 229.75,229.75c0,126.89 -102.86,229.75 -229.75,229.75c-126.89,0 -229.75,-102.86 -229.75,-229.75C20.66,123.36 123.53,20.5 250.41,20.5ZM250.85,161.82c-49.09,0 -88.88,39.79 -88.88,88.88c0,49.09 39.79,88.88 88.88,88.88c49.09,0 88.88,-39.79 88.88,-88.88c0,-49.09 -39.79,-88.88 -88.88,-88.88Z">
|
||||||
<path
|
<aapt:attr name="android:fillColor">
|
||||||
android:pathData="M74.66,106.67c0,5.89 -4.78,10.66 -10.67,10.66c-5.89,0 -10.66,-4.77 -10.66,-10.66S58.1,96 63.99,96C69.88,96 74.66,100.78 74.66,106.67z"
|
<gradient
|
||||||
android:fillColor="#E6E9ED"/>
|
android:startX="116.21"
|
||||||
<path
|
android:startY="67.61"
|
||||||
android:pathData="M74.66,384.01c0,5.88 -4.78,10.66 -10.67,10.66c-5.89,0 -10.66,-4.78 -10.66,-10.66c0,-5.91 4.77,-10.69 10.66,-10.69C69.88,373.33 74.66,378.11 74.66,384.01z"
|
android:endX="403.29"
|
||||||
android:fillColor="#E6E9ED"/>
|
android:endY="429.34"
|
||||||
<path
|
android:type="linear">
|
||||||
android:pathData="M448,123.73h-21.34v203.19l-40.31,50.41v0.02c-1.47,1.83 -2.34,4.14 -2.34,6.67c0,5.88 4.78,10.66 10.66,10.66c3.38,0 6.38,-1.56 8.33,-4h0.02l42.66,-53.34l0,0c1.47,-1.81 2.34,-4.13 2.34,-6.66V123.73z"
|
<item android:offset="0.0" android:color="#66060606" />
|
||||||
android:fillColor="#E6E9ED"/>
|
<item android:offset="1.0" android:color="#CC060606" />
|
||||||
<path
|
</gradient>
|
||||||
android:pathData="M437.33,149.33c-11.77,0 -21.33,-9.56 -21.33,-21.33s9.56,-21.33 21.33,-21.33s21.33,9.56 21.33,21.33S449.09,149.33 437.33,149.33z"
|
</aapt:attr>
|
||||||
android:fillColor="#E6E9ED"/>
|
</path>
|
||||||
<path
|
|
||||||
android:pathData="M437.33,96c-17.67,0 -32,14.33 -32,32s14.33,32 32,32s32,-14.33 32,-32S455,96 437.33,96zM437.33,138.67c-5.89,0 -10.67,-4.8 -10.67,-10.67c0,-5.88 4.78,-10.67 10.67,-10.67s10.67,4.8 10.67,10.67C448,133.88 443.22,138.67 437.33,138.67z"
|
<path
|
||||||
android:fillColor="#CCD1D9"/>
|
android:pathData="M453.23,307.8c-18.5,72.24 -73.8,129.26 -144.2,148.92l-36.39,-138.74c21.97,-7.21 39.22,-24.84 45.88,-47.06l134.71,36.88Z">
|
||||||
<path
|
<aapt:attr name="android:fillColor">
|
||||||
android:pathData="M405.33,245.33c0,82.48 -66.86,149.34 -149.33,149.34c-82.47,0 -149.33,-66.86 -149.33,-149.34C106.66,162.86 173.52,96 255.99,96C338.47,96 405.33,162.86 405.33,245.33z"
|
<gradient
|
||||||
android:fillColor="#434A54"/>
|
android:startX="420.63"
|
||||||
<path
|
android:startY="403.74"
|
||||||
android:pathData="M266.66,149.33c0,-5.89 -4.77,-10.66 -10.67,-10.66c-58.91,0 -106.66,47.75 -106.66,106.65l0,0c0,5.89 4.77,10.67 10.67,10.67s10.67,-4.78 10.67,-10.67l0,0c0,-22.78 8.88,-44.22 24.99,-60.33c16.12,-16.13 37.55,-25 60.34,-25C261.89,160 266.66,155.22 266.66,149.33z"
|
android:endX="78.4"
|
||||||
android:fillColor="#656D78"/>
|
android:endY="117.92"
|
||||||
<path
|
android:type="linear">
|
||||||
android:pathData="M352,234.67c-5.9,0 -10.67,4.77 -10.67,10.66l0,0c0,22.8 -8.88,44.23 -24.98,60.34c-16.13,16.13 -37.56,25 -60.35,25c-5.89,0 -10.66,4.78 -10.66,10.66c0,5.91 4.77,10.69 10.66,10.69c58.91,0 106.66,-47.77 106.66,-106.69C362.65,239.44 357.89,234.67 352,234.67z"
|
<item android:offset="0.0" android:color="#33FFFFFF" />
|
||||||
android:fillColor="#656D78"/>
|
<item android:offset="1.0" android:color="#4DFFFFFF" />
|
||||||
<path
|
</gradient>
|
||||||
android:pathData="M255.99,288.01c-23.52,0 -42.66,-19.16 -42.66,-42.69c0,-23.52 19.14,-42.66 42.66,-42.66c23.54,0 42.66,19.14 42.66,42.66C298.65,268.86 279.53,288.01 255.99,288.01z"
|
</aapt:attr>
|
||||||
android:fillColor="#FFCE54"/>
|
</path>
|
||||||
<path
|
|
||||||
android:pathData="M255.99,192c-29.45,0 -53.33,23.88 -53.33,53.33s23.88,53.34 53.33,53.34c29.46,0 53.34,-23.89 53.34,-53.34S285.45,192 255.99,192zM255.99,277.34c-17.64,0 -32,-14.36 -32,-32.02c0,-17.64 14.36,-32 32,-32c17.65,0 32.01,14.36 32.01,32C288,262.98 273.64,277.34 255.99,277.34z"
|
<path
|
||||||
android:fillColor="#F6BB42"/>
|
android:pathData="M228.3,183.04c-21.73,7.15 -38.82,24.5 -45.62,46.39L47.5,192.42c18.5,-72.24 73.8,-129.26 144.2,-148.92l36.6,139.54Z">
|
||||||
<path
|
<aapt:attr name="android:fillColor">
|
||||||
android:pathData="M266.66,245.33c0,5.89 -4.77,10.67 -10.67,10.67c-5.89,0 -10.66,-4.78 -10.66,-10.67s4.77,-10.66 10.66,-10.66C261.89,234.67 266.66,239.44 266.66,245.33z"
|
<gradient
|
||||||
android:fillColor="#434A54"/>
|
android:startX="420.63"
|
||||||
<path
|
android:startY="403.74"
|
||||||
android:pathData="M74.66,234.67H53.33c-5.89,0 -10.66,4.77 -10.66,10.66s4.77,10.67 10.66,10.67h21.34c5.89,0 10.66,-4.78 10.66,-10.67S80.56,234.67 74.66,234.67z"
|
android:endX="78.4"
|
||||||
android:fillColor="#434A54"/>
|
android:endY="117.92"
|
||||||
|
android:type="linear">
|
||||||
|
<item android:offset="0.0" android:color="#33FFFFFF" />
|
||||||
|
<item android:offset="1.0" android:color="#4DFFFFFF" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:fillColor="#66FFFFFF"
|
||||||
|
android:pathData="M250.5,179.5c39.21,0 71,31.79 71,71s-31.79,71 -71,71s-71,-31.79 -71,-71s31.79,-71 71,-71ZM250,235c-8.28,0 -15,6.72 -15,15c0,8.28 6.72,15 15,15c8.28,0 15,-6.72 15,-15c0,-8.28 -6.72,-15 -15,-15Z" />
|
||||||
|
</group>
|
||||||
</vector>
|
</vector>
|
||||||
@@ -1,51 +1,78 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="800dp"
|
xmlns:aapt="http://schemas.android.com/aapt"
|
||||||
android:height="800dp"
|
android:width="108dp"
|
||||||
android:viewportWidth="512"
|
android:height="108dp"
|
||||||
android:viewportHeight="512">
|
android:viewportWidth="108"
|
||||||
<path
|
android:viewportHeight="108">
|
||||||
android:pathData="M512,437.33c0,11.78 -9.56,21.34 -21.34,21.34H21.33C9.55,458.67 0,449.11 0,437.33V96c0,-11.78 9.55,-21.33 21.33,-21.33h469.33c11.78,0 21.34,9.55 21.34,21.33L512,437.33L512,437.33z"
|
|
||||||
android:fillColor="#DA4453"/>
|
<group
|
||||||
<path
|
android:scaleX="0.16"
|
||||||
android:pathData="M512,416.01c0,11.78 -9.56,21.31 -21.34,21.31H21.33C9.55,437.33 0,427.8 0,416.01V74.67c0,-11.78 9.55,-21.34 21.33,-21.34h469.33c11.78,0 21.34,9.56 21.34,21.34L512,416.01L512,416.01z"
|
android:scaleY="0.16"
|
||||||
android:fillColor="#ED5564"/>
|
android:translateX="14.0"
|
||||||
<path
|
android:translateY="14.0">
|
||||||
android:pathData="M63.99,160c-5.89,0 -10.66,4.78 -10.66,10.67v149.34c0,5.88 4.77,10.66 10.66,10.66c5.89,0 10.67,-4.78 10.67,-10.66V170.67C74.66,164.78 69.88,160 63.99,160z"
|
|
||||||
android:fillColor="#DA4453"/>
|
<path
|
||||||
<path
|
android:pathData="M250,0c138.07,0 250,111.93 250,250S388.07,500 250,500 0,388.07 0,250 111.93,0 250,0ZM250,235c-8.28,0 -15,6.72 -15,15c0,8.28 6.72,15 15,15c8.28,0 15,-6.72 15,-15c0,-8.28 -6.72,-15 -15,-15Z">
|
||||||
android:pathData="M74.66,106.67c0,5.89 -4.78,10.66 -10.67,10.66c-5.89,0 -10.66,-4.77 -10.66,-10.66S58.1,96 63.99,96C69.88,96 74.66,100.78 74.66,106.67z"
|
<aapt:attr name="android:fillColor">
|
||||||
android:fillColor="#E6E9ED"/>
|
<gradient
|
||||||
<path
|
android:startX="122.34"
|
||||||
android:pathData="M74.66,384.01c0,5.88 -4.78,10.66 -10.67,10.66c-5.89,0 -10.66,-4.78 -10.66,-10.66c0,-5.91 4.77,-10.69 10.66,-10.69C69.88,373.33 74.66,378.11 74.66,384.01z"
|
android:startY="23.55"
|
||||||
android:fillColor="#E6E9ED"/>
|
android:endX="377.69"
|
||||||
<path
|
android:endY="465.83"
|
||||||
android:pathData="M448,123.73h-21.34v203.19l-40.31,50.41v0.02c-1.47,1.83 -2.34,4.14 -2.34,6.67c0,5.88 4.78,10.66 10.66,10.66c3.38,0 6.38,-1.56 8.33,-4h0.02l42.66,-53.34l0,0c1.47,-1.81 2.34,-4.13 2.34,-6.66V123.73z"
|
android:type="linear">
|
||||||
android:fillColor="#E6E9ED"/>
|
<item android:offset="0.0" android:color="#FFEC4A4A" />
|
||||||
<path
|
<item android:offset="1.0" android:color="#FFEC4A4A" />
|
||||||
android:pathData="M437.33,149.33c-11.77,0 -21.33,-9.56 -21.33,-21.33s9.56,-21.33 21.33,-21.33s21.33,9.56 21.33,21.33S449.09,149.33 437.33,149.33z"
|
</gradient>
|
||||||
android:fillColor="#E6E9ED"/>
|
</aapt:attr>
|
||||||
<path
|
</path>
|
||||||
android:pathData="M437.33,96c-17.67,0 -32,14.33 -32,32s14.33,32 32,32s32,-14.33 32,-32S455,96 437.33,96zM437.33,138.67c-5.89,0 -10.67,-4.8 -10.67,-10.67c0,-5.88 4.78,-10.67 10.67,-10.67s10.67,4.8 10.67,10.67C448,133.88 443.22,138.67 437.33,138.67z"
|
|
||||||
android:fillColor="#CCD1D9"/>
|
<path
|
||||||
<path
|
android:pathData="M250.41,20.5c126.89,0 229.75,102.86 229.75,229.75c0,126.89 -102.86,229.75 -229.75,229.75c-126.89,0 -229.75,-102.86 -229.75,-229.75C20.66,123.36 123.53,20.5 250.41,20.5ZM250.85,161.82c-49.09,0 -88.88,39.79 -88.88,88.88c0,49.09 39.79,88.88 88.88,88.88c49.09,0 88.88,-39.79 88.88,-88.88c0,-49.09 -39.79,-88.88 -88.88,-88.88Z">
|
||||||
android:pathData="M405.33,245.33c0,82.48 -66.86,149.34 -149.33,149.34c-82.47,0 -149.33,-66.86 -149.33,-149.34C106.66,162.86 173.52,96 255.99,96C338.47,96 405.33,162.86 405.33,245.33z"
|
<aapt:attr name="android:fillColor">
|
||||||
android:fillColor="#434A54"/>
|
<gradient
|
||||||
<path
|
android:startX="116.21"
|
||||||
android:pathData="M266.66,149.33c0,-5.89 -4.77,-10.66 -10.67,-10.66c-58.91,0 -106.66,47.75 -106.66,106.65l0,0c0,5.89 4.77,10.67 10.66,10.67s10.67,-4.78 10.67,-10.67l0,0c0,-22.78 8.88,-44.22 24.99,-60.33c16.12,-16.13 37.55,-25 60.34,-25C261.89,160 266.66,155.22 266.66,149.33z"
|
android:startY="67.61"
|
||||||
android:fillColor="#656D78"/>
|
android:endX="403.29"
|
||||||
<path
|
android:endY="429.34"
|
||||||
android:pathData="M352,234.67c-5.9,0 -10.67,4.77 -10.67,10.66l0,0c0,22.8 -8.88,44.23 -24.98,60.34c-16.13,16.13 -37.56,25 -60.35,25c-5.89,0 -10.66,4.78 -10.66,10.66c0,5.91 4.77,10.69 10.66,10.69c58.91,0 106.66,-47.77 106.66,-106.69C362.65,239.44 357.89,234.67 352,234.67z"
|
android:type="linear">
|
||||||
android:fillColor="#656D78"/>
|
<item android:offset="0.0" android:color="#66060606" />
|
||||||
<path
|
<item android:offset="1.0" android:color="#CC060606" />
|
||||||
android:pathData="M255.99,288.01c-23.52,0 -42.66,-19.16 -42.66,-42.69c0,-23.52 19.14,-42.66 42.66,-42.66c23.54,0 42.66,19.14 42.66,42.66C298.65,268.86 279.53,288.01 255.99,288.01z"
|
</gradient>
|
||||||
android:fillColor="#FFCE54"/>
|
</aapt:attr>
|
||||||
<path
|
</path>
|
||||||
android:pathData="M255.99,192c-29.45,0 -53.33,23.88 -53.33,53.33s23.88,53.34 53.33,53.34c29.46,0 53.34,-23.89 53.34,-53.34S285.45,192 255.99,192zM255.99,277.34c-17.64,0 -32,-14.36 -32,-32.02c0,-17.64 14.36,-32 32,-32c17.65,0 32.01,14.36 32.01,32C288,262.98 273.64,277.34 255.99,277.34z"
|
|
||||||
android:fillColor="#F6BB42"/>
|
<path
|
||||||
<path
|
android:pathData="M453.23,307.8c-18.5,72.24 -73.8,129.26 -144.2,148.92l-36.39,-138.74c21.97,-7.21 39.22,-24.84 45.88,-47.06l134.71,36.88Z">
|
||||||
android:pathData="M266.66,245.33c0,5.89 -4.77,10.67 -10.67,10.67c-5.89,0 -10.66,-4.78 -10.66,-10.67s4.77,-10.66 10.66,-10.66C261.89,234.67 266.66,239.44 266.66,245.33z"
|
<aapt:attr name="android:fillColor">
|
||||||
android:fillColor="#434A54"/>
|
<gradient
|
||||||
<path
|
android:startX="420.63"
|
||||||
android:pathData="M74.66,234.67H53.33c-5.89,0 -10.66,4.77 -10.66,10.66s4.77,10.67 10.66,10.67h21.34c5.89,0 10.66,-4.78 10.66,-10.67S80.56,234.67 74.66,234.67z"
|
android:startY="403.74"
|
||||||
android:fillColor="#434A54"/>
|
android:endX="78.4"
|
||||||
|
android:endY="117.92"
|
||||||
|
android:type="linear">
|
||||||
|
<item android:offset="0.0" android:color="#33FFFFFF" />
|
||||||
|
<item android:offset="1.0" android:color="#4DFFFFFF" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:pathData="M228.3,183.04c-21.73,7.15 -38.82,24.5 -45.62,46.39L47.5,192.42c18.5,-72.24 73.8,-129.26 144.2,-148.92l36.6,139.54Z">
|
||||||
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:startX="420.63"
|
||||||
|
android:startY="403.74"
|
||||||
|
android:endX="78.4"
|
||||||
|
android:endY="117.92"
|
||||||
|
android:type="linear">
|
||||||
|
<item android:offset="0.0" android:color="#33FFFFFF" />
|
||||||
|
<item android:offset="1.0" android:color="#4DFFFFFF" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:fillColor="#66FFFFFF"
|
||||||
|
android:pathData="M250.5,179.5c39.21,0 71,31.79 71,71s-31.79,71 -71,71s-71,-31.79 -71,-71s31.79,-71 71,-71ZM250,235c-8.28,0 -15,6.72 -15,15c0,8.28 6.72,15 15,15c8.28,0 15,-6.72 15,-15c0,-8.28 -6.72,-15 -15,-15Z" />
|
||||||
|
</group>
|
||||||
</vector>
|
</vector>
|
||||||
@@ -47,6 +47,19 @@
|
|||||||
app:behavior_hideable="true"
|
app:behavior_hideable="true"
|
||||||
app:behavior_peekHeight="@dimen/bottom_sheet_peek_height"
|
app:behavior_peekHeight="@dimen/bottom_sheet_peek_height"
|
||||||
app:layout_behavior="@string/bottom_sheet_behavior" />
|
app:layout_behavior="@string/bottom_sheet_behavior" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/offline_mode_text_view"
|
||||||
|
style="@style/NoConnectionTextView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:layout_gravity="top"
|
||||||
|
android:padding="2dp"
|
||||||
|
android:text="@string/activity_info_offline_mode"
|
||||||
|
android:textSize="11sp"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
||||||
<com.google.android.material.navigation.NavigationView
|
<com.google.android.material.navigation.NavigationView
|
||||||
@@ -57,13 +70,4 @@
|
|||||||
app:menu="@menu/nav_drawer"
|
app:menu="@menu/nav_drawer"
|
||||||
app:headerLayout="@layout/nav_drawer_header" />
|
app:headerLayout="@layout/nav_drawer_header" />
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/offline_mode_text_view"
|
|
||||||
style="@style/NoConnectionTextView"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/activity_info_offline_mode"
|
|
||||||
android:textSize="6sp"
|
|
||||||
android:visibility="gone" />
|
|
||||||
</androidx.drawerlayout.widget.DrawerLayout>
|
</androidx.drawerlayout.widget.DrawerLayout>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.drawerlayout.widget.DrawerLayout
|
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:id="@+id/drawer_layout"
|
android:id="@+id/drawer_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -37,6 +36,17 @@
|
|||||||
android:paddingEnd="24dp"
|
android:paddingEnd="24dp"
|
||||||
app:menu="@menu/bottom_nav_menu" />
|
app:menu="@menu/bottom_nav_menu" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/offline_mode_text_view"
|
||||||
|
style="@style/NoConnectionTextView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:layout_gravity="top"
|
||||||
|
android:padding="2dp"
|
||||||
|
android:text="@string/activity_info_offline_mode"
|
||||||
|
android:textSize="11sp"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
||||||
@@ -60,13 +70,4 @@
|
|||||||
app:menu="@menu/nav_drawer"
|
app:menu="@menu/nav_drawer"
|
||||||
app:headerLayout="@layout/nav_drawer_header" />
|
app:headerLayout="@layout/nav_drawer_header" />
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/offline_mode_text_view"
|
|
||||||
style="@style/NoConnectionTextView"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/activity_info_offline_mode"
|
|
||||||
android:textSize="6sp"
|
|
||||||
android:visibility="gone" />
|
|
||||||
</androidx.drawerlayout.widget.DrawerLayout>
|
</androidx.drawerlayout.widget.DrawerLayout>
|
||||||
|
|||||||
130
app/src/main/res/layout/bottom_sheet_playlist_dialog.xml
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="20dp"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:layout_marginEnd="12dp"
|
||||||
|
android:clipChildren="false">
|
||||||
|
|
||||||
|
<!-- Header -->
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/playlist_cover_image_view"
|
||||||
|
android:layout_width="54dp"
|
||||||
|
android:layout_height="54dp"
|
||||||
|
android:layout_margin="2dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<ToggleButton
|
||||||
|
android:id="@+id/button_favorite"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:background="@drawable/button_favorite_selector"
|
||||||
|
android:checked="false"
|
||||||
|
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:text=""
|
||||||
|
android:textOff=""
|
||||||
|
android:textOn=""
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/playlist_title_text_view"
|
||||||
|
style="@style/LabelMedium"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:ellipsize="marquee"
|
||||||
|
android:paddingStart="12dp"
|
||||||
|
android:paddingEnd="12dp"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:text="@string/label_placeholder"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/button_favorite"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/playlist_cover_image_view"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/playlist_count_text_view"
|
||||||
|
style="@style/LabelSmall"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingStart="12dp"
|
||||||
|
android:paddingEnd="12dp"
|
||||||
|
android:text="@string/label_placeholder"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/button_favorite"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/playlist_cover_image_view"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/playlist_title_text_view" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/song_asset_link_row"
|
||||||
|
layout="@layout/view_asset_link_row"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingStart="20dp"
|
||||||
|
android:paddingEnd="12dp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/option_linear_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingTop="8dp"
|
||||||
|
android:paddingBottom="12dp"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/play_next_text_view"
|
||||||
|
style="@style/LabelMedium"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
|
android:clickable="true"
|
||||||
|
android:paddingStart="20dp"
|
||||||
|
android:paddingTop="12dp"
|
||||||
|
android:paddingEnd="20dp"
|
||||||
|
android:paddingBottom="12dp"
|
||||||
|
android:text="@string/song_bottom_sheet_play_next" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/add_to_queue_text_view"
|
||||||
|
style="@style/LabelMedium"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
|
android:clickable="true"
|
||||||
|
android:paddingStart="20dp"
|
||||||
|
android:paddingTop="12dp"
|
||||||
|
android:paddingEnd="20dp"
|
||||||
|
android:paddingBottom="12dp"
|
||||||
|
android:text="@string/song_bottom_sheet_add_to_queue" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/share_text_view"
|
||||||
|
style="@style/LabelMedium"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
|
android:clickable="true"
|
||||||
|
android:paddingStart="20dp"
|
||||||
|
android:paddingTop="12dp"
|
||||||
|
android:paddingEnd="20dp"
|
||||||
|
android:paddingBottom="12dp"
|
||||||
|
android:text="@string/song_bottom_sheet_share"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
@@ -330,13 +330,13 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<!-- slideview -->
|
<!-- slideview -->
|
||||||
<androidx.viewpager2.widget.ViewPager2
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/discover_song_view_pager"
|
android:id="@+id/discover_song_recycler_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="212dp"
|
android:layout_height="wrap_content"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:paddingTop="8dp"
|
android:paddingTop="8dp"
|
||||||
android:paddingBottom="16dp" />
|
android:paddingBottom="8dp" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<!-- Similar tracks -->
|
<!-- Similar tracks -->
|
||||||
|
|||||||
@@ -36,7 +36,6 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingBottom="8dp"
|
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:visibility="visible">
|
tools:visibility="visible">
|
||||||
|
|
||||||
|
|||||||
@@ -108,6 +108,22 @@
|
|||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:paddingTop="8dp"
|
android:paddingTop="8dp"
|
||||||
android:paddingBottom="8dp" />
|
android:paddingBottom="8dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/allSongs"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:text="@string/search_all_songs_loading"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/allsongsview"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|||||||
@@ -1,6 +1,22 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent">
|
||||||
android:paddingTop="20dp"
|
|
||||||
android:paddingBottom="@dimen/global_padding_bottom" />
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
|
android:id="@+id/settings_toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
android:background="?attr/colorSurface"
|
||||||
|
app:layout_collapseMode="pin"
|
||||||
|
app:navigationIcon="@drawable/ic_arrow_back" />
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/settings_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_height="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:paddingHorizontal="16dp">
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingStart="8dp">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/discover_song_cover_image_view"
|
android:id="@+id/discover_song_cover_image_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="344dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="172dp"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
android:pivotX="50%"
|
android:pivotX="50%"
|
||||||
android:pivotY="50%"
|
android:pivotY="50%"
|
||||||
@@ -16,30 +17,34 @@
|
|||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/title_discover_song_label"
|
android:id="@+id/title_discover_song_label"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginLeft="16dp"
|
android:layout_marginTop="4dp"
|
||||||
android:layout_marginTop="18dp"
|
android:layout_marginLeft="4dp"
|
||||||
android:layout_marginRight="16dp"
|
android:layout_marginRight="4dp"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:fontFamily="@font/inter"
|
android:fontFamily="@font/inter"
|
||||||
android:maxLines="2"
|
android:maxLines="2"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/discover_song_cover_image_view"
|
||||||
android:textColor="@color/gradientTitleColor"
|
android:textColor="@color/gradientTitleColor"
|
||||||
android:textFontWeight="400"
|
android:textFontWeight="400"
|
||||||
android:textSize="20sp" />
|
android:textSize="20sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/album_discover_song_label"
|
android:id="@+id/album_discover_song_label"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/title_discover_song_label"
|
android:layout_marginLeft="4dp"
|
||||||
android:layout_marginLeft="16dp"
|
android:layout_marginRight="4dp"
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
android:drawablePadding="10dp"
|
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:fontFamily="@font/inter"
|
android:fontFamily="@font/inter"
|
||||||
android:maxLines="1"
|
android:maxLines="2"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/title_discover_song_label"
|
||||||
android:textColor="@color/gradientSubtitleColor"
|
android:textColor="@color/gradientSubtitleColor"
|
||||||
android:textFontWeight="400"
|
android:textFontWeight="400"
|
||||||
android:textSize="14sp" />
|
android:textSize="14sp" />
|
||||||
</RelativeLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
@@ -4,13 +4,13 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingEnd="12dp"
|
android:paddingEnd="8dp"
|
||||||
android:paddingBottom="8dp">
|
android:paddingBottom="4dp">
|
||||||
|
|
||||||
<androidx.cardview.widget.CardView
|
<androidx.cardview.widget.CardView
|
||||||
android:id="@+id/card_view"
|
android:id="@+id/card_view"
|
||||||
android:layout_width="172dp"
|
android:layout_width="120dp"
|
||||||
android:layout_height="72dp"
|
android:layout_height="54dp"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
card_view:cardCornerRadius="4dp"
|
card_view:cardCornerRadius="4dp"
|
||||||
card_view:cardElevation="2dp"
|
card_view:cardElevation="2dp"
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
<androidx.cardview.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
<androidx.cardview.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||||
android:id="@+id/card_view"
|
android:id="@+id/card_view"
|
||||||
android:layout_width="196dp"
|
android:layout_width="172dp"
|
||||||
android:layout_height="54dp"
|
android:layout_height="54dp"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
card_view:cardCornerRadius="4dp"
|
card_view:cardCornerRadius="4dp"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<background android:drawable="@color/ic_launcher_background"/>
|
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
|
<monochrome android:drawable="@drawable/ic_launcher_monochrome"/>
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<background android:drawable="@color/ic_launcher_background"/>
|
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
|
||||||
</adaptive-icon>
|
|
||||||
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 9.0 KiB |
@@ -329,6 +329,11 @@
|
|||||||
android:name="com.cappielloantonio.tempo.ui.fragment.bottomsheetdialog.SongBottomSheetDialog"
|
android:name="com.cappielloantonio.tempo.ui.fragment.bottomsheetdialog.SongBottomSheetDialog"
|
||||||
android:label="SongBottomSheetDialog"
|
android:label="SongBottomSheetDialog"
|
||||||
tools:layout="@layout/bottom_sheet_song_dialog" />
|
tools:layout="@layout/bottom_sheet_song_dialog" />
|
||||||
|
<dialog
|
||||||
|
android:id="@+id/playlistBottomSheetDialog"
|
||||||
|
android:name="com.cappielloantonio.tempo.ui.fragment.bottomsheetdialog.PlaylistBottomSheetDialog"
|
||||||
|
android:label="PlaylistBottomSheetDialog"
|
||||||
|
tools:layout="@layout/bottom_sheet_playlist_dialog" />
|
||||||
<dialog
|
<dialog
|
||||||
android:id="@+id/artistBottomSheetDialog"
|
android:id="@+id/artistBottomSheetDialog"
|
||||||
android:name="com.cappielloantonio.tempo.ui.fragment.bottomsheetdialog.ArtistBottomSheetDialog"
|
android:name="com.cappielloantonio.tempo.ui.fragment.bottomsheetdialog.ArtistBottomSheetDialog"
|
||||||
|
|||||||
@@ -263,4 +263,74 @@
|
|||||||
<item>3</item>
|
<item>3</item>
|
||||||
<item>4</item>
|
<item>4</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
<string-array name="landscape_items_per_row">
|
||||||
|
<item>3"</item>
|
||||||
|
<item>4</item>
|
||||||
|
<item>5</item>
|
||||||
|
<item>6</item>
|
||||||
|
<item>7</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="landscape_items_per_row_values">
|
||||||
|
<item>3</item>
|
||||||
|
<item>4</item>
|
||||||
|
<item>5</item>
|
||||||
|
<item>6</item>
|
||||||
|
<item>7</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="tile_size_titles">
|
||||||
|
<item>Muy pequeño</item>
|
||||||
|
<item>Pequeño</item>
|
||||||
|
<item>Mediano</item>
|
||||||
|
<item>Grande</item>
|
||||||
|
<item>Por defecto</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="tile_size_divisor">
|
||||||
|
<item>6</item>
|
||||||
|
<item>5</item>
|
||||||
|
<item>4</item>
|
||||||
|
<item>3</item>
|
||||||
|
<item>2</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<!-- Add by MFO -->
|
||||||
|
<string-array name="aa_tab_titles">
|
||||||
|
<item>No mostrar</item>
|
||||||
|
<item>Inicio</item>
|
||||||
|
<item>Reciente</item>
|
||||||
|
<item>Álbumes</item>
|
||||||
|
<item>Artistas</item>
|
||||||
|
<item>Listas</item>
|
||||||
|
<item>Pódcasts</item>
|
||||||
|
<item>Radio</item>
|
||||||
|
<item>Carpeta</item>
|
||||||
|
<item>Álbumes más reproducidos</item>
|
||||||
|
<!-- <item>Pistas reproducidas</item> -->
|
||||||
|
<item>Álbumes añadidos</item>
|
||||||
|
<!-- <item>Para ti</item> -->
|
||||||
|
<item>Pistas favoritas</item>
|
||||||
|
<item>Álbumes favoritos</item>
|
||||||
|
<item>Artistas favoritos</item>
|
||||||
|
<item>Aleatorio</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="aa_tab_values">
|
||||||
|
<item>-1</item>
|
||||||
|
<item>0</item>
|
||||||
|
<item>1</item>
|
||||||
|
<item>2</item>
|
||||||
|
<item>3</item>
|
||||||
|
<item>4</item>
|
||||||
|
<item>5</item>
|
||||||
|
<item>6</item>
|
||||||
|
<item>7</item>
|
||||||
|
<item>8</item>
|
||||||
|
<item>9</item>
|
||||||
|
<item>10</item>
|
||||||
|
<item>11</item>
|
||||||
|
<item>12</item>
|
||||||
|
<item>13</item>
|
||||||
|
<item>14</item>
|
||||||
|
<item>15</item>
|
||||||
|
</string-array>
|
||||||
|
<!-- end Add by MFO -->
|
||||||
</resources>
|
</resources>
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="album_page_tracks_count_and_duration">%1$d pistas • %2$d minutos</string>
|
<string name="album_page_tracks_count_and_duration">%1$d pistas • %2$d minutos</string>
|
||||||
<string name="app_name">Tempus</string>
|
<string name="app_name">Tempus</string>
|
||||||
|
<string name="aa_starred_tracks">★ Pistas</string>
|
||||||
<string name="activity_battery_optimizations_conclusion">Si tienes problemas, visita https://dontkillmyapp.com. Ofrece instrucciones detalladas para desactivar características de ahorro de energía que podrían afectar al rendimiento de la app.</string>
|
<string name="activity_battery_optimizations_conclusion">Si tienes problemas, visita https://dontkillmyapp.com. Ofrece instrucciones detalladas para desactivar características de ahorro de energía que podrían afectar al rendimiento de la app.</string>
|
||||||
<string name="activity_battery_optimizations_summary">Por favor, desactiva las optimizaciones de batería para continuar la reproducción multimedia mientras la pantalla está apagada.</string>
|
<string name="activity_battery_optimizations_summary">Por favor, desactiva las optimizaciones de batería para continuar la reproducción multimedia mientras la pantalla está apagada.</string>
|
||||||
<string name="activity_battery_optimizations_title">Optimizaciones de batería</string>
|
<string name="activity_battery_optimizations_title">Optimizaciones de batería</string>
|
||||||
@@ -227,9 +228,12 @@
|
|||||||
<string name="playlist_chooser_dialog_create_button">Crear</string>
|
<string name="playlist_chooser_dialog_create_button">Crear</string>
|
||||||
<string name="playlist_chooser_dialog_title">Añadir a una lista de reproducción</string>
|
<string name="playlist_chooser_dialog_title">Añadir a una lista de reproducción</string>
|
||||||
<string name="playlist_chooser_dialog_toast_add_failure">Error al añadir a la lista</string>
|
<string name="playlist_chooser_dialog_toast_add_failure">Error al añadir a la lista</string>
|
||||||
|
<string name="playlist_chooser_dialog_toast_remove_failure">Error al eliminar la canción de la lista</string>
|
||||||
<string name="playlist_chooser_dialog_toast_all_skipped">Todas las pistas se han descartado porque están repetidas</string>
|
<string name="playlist_chooser_dialog_toast_all_skipped">Todas las pistas se han descartado porque están repetidas</string>
|
||||||
<string name="playlist_chooser_dialog_visibility_public">Público</string>
|
<string name="playlist_chooser_dialog_visibility_public">Público</string>
|
||||||
<string name="playlist_chooser_dialog_visibility_private">Privado</string>
|
<string name="playlist_chooser_dialog_visibility_private">Privado</string>
|
||||||
|
<string name="playlist_chooser_dialog_visibility_switch_label">Marcar la lista de reproducción como pública</string>
|
||||||
|
<string name="playlist_chooser_dialog_visibility_summary">El servidor actualiza la visibilidad en cada petición. Por defecto está configurada como privada.</string>
|
||||||
<string name="playlist_counted_tracks">%1$d pistas • %2$s</string>
|
<string name="playlist_counted_tracks">%1$d pistas • %2$s</string>
|
||||||
<string name="playlist_duration">Duración • %1$s</string>
|
<string name="playlist_duration">Duración • %1$s</string>
|
||||||
<string name="playlist_editor_dialog_action_delete_toast">Pulsación larga para eliminar</string>
|
<string name="playlist_editor_dialog_action_delete_toast">Pulsación larga para eliminar</string>
|
||||||
@@ -290,6 +294,7 @@
|
|||||||
<string name="server_signup_dialog_hint_password">Contraseña</string>
|
<string name="server_signup_dialog_hint_password">Contraseña</string>
|
||||||
<string name="server_signup_dialog_hint_url">URL del servidor</string>
|
<string name="server_signup_dialog_hint_url">URL del servidor</string>
|
||||||
<string name="server_signup_dialog_hint_username">Nombre de usuario</string>
|
<string name="server_signup_dialog_hint_username">Nombre de usuario</string>
|
||||||
|
<string name="server_signup_dialog_hint_client_certificate">Certificado del cliente (opcional)</string>
|
||||||
<string name="server_signup_dialog_negative_button">Cancelar</string>
|
<string name="server_signup_dialog_negative_button">Cancelar</string>
|
||||||
<string name="server_signup_dialog_neutral_button">Eliminar</string>
|
<string name="server_signup_dialog_neutral_button">Eliminar</string>
|
||||||
<string name="server_signup_dialog_positive_button">Guardar</string>
|
<string name="server_signup_dialog_positive_button">Guardar</string>
|
||||||
@@ -339,6 +344,7 @@
|
|||||||
<string name="settings_podcast">Mostrar pódcasts</string>
|
<string name="settings_podcast">Mostrar pódcasts</string>
|
||||||
<string name="settings_podcast_summary">Si se habilita, se mostrará la sección de pódcasts. Reinicia la aplicación para que los cambios surtan efecto.</string>
|
<string name="settings_podcast_summary">Si se habilita, se mostrará la sección de pódcasts. Reinicia la aplicación para que los cambios surtan efecto.</string>
|
||||||
<string name="settings_playlist_sort">Ordenar listas de reproducción</string>
|
<string name="settings_playlist_sort">Ordenar listas de reproducción</string>
|
||||||
|
<string name="settings_androidauto_fourth_tab">Vista de la cuarta pestaña</string>
|
||||||
<string name="settings_audio_quality">Mostrar calidad de audio</string>
|
<string name="settings_audio_quality">Mostrar calidad de audio</string>
|
||||||
<string name="settings_audio_quality_summary">La tasa de bits y el formato de audio se mostrarán para cada pista de audio.</string>
|
<string name="settings_audio_quality_summary">La tasa de bits y el formato de audio se mostrarán para cada pista de audio.</string>
|
||||||
<string name="settings_song_rating_summary">Si se habilita, muestra la valoración de la pista como barra de 5 estrellas en la página del control de reproducción.\n\n*Requiere reiniciar la aplicación</string>
|
<string name="settings_song_rating_summary">Si se habilita, muestra la valoración de la pista como barra de 5 estrellas en la página del control de reproducción.\n\n*Requiere reiniciar la aplicación</string>
|
||||||
@@ -363,6 +369,7 @@
|
|||||||
<string name="track_info_sampling_rate">Tasa de muestreo</string>
|
<string name="track_info_sampling_rate">Tasa de muestreo</string>
|
||||||
<string name="track_info_content_type">Tipo de contenido</string>
|
<string name="track_info_content_type">Tipo de contenido</string>
|
||||||
<string name="track_info_dialog_positive_button">Aceptar</string>
|
<string name="track_info_dialog_positive_button">Aceptar</string>
|
||||||
|
<string name="track_info_station">Emisora</string>
|
||||||
<string name="track_info_transcoded_content_type">Tipo de contenido en la transcodificación</string>
|
<string name="track_info_transcoded_content_type">Tipo de contenido en la transcodificación</string>
|
||||||
<string name="track_info_transcoded_suffix">Extensión en la transcodificación</string>
|
<string name="track_info_transcoded_suffix">Extensión en la transcodificación</string>
|
||||||
<string name="track_info_year">Año</string>
|
<string name="track_info_year">Año</string>
|
||||||
@@ -396,6 +403,7 @@
|
|||||||
<string name="settings_summary_scrobble">El scrobbling es una característica que permite a tu dispositivo enviar información sobre las pistas que escuchas al servidor de música. Esta información ayuda a crear recomendaciones personalizadas basadas en tus gustos musicales.</string>
|
<string name="settings_summary_scrobble">El scrobbling es una característica que permite a tu dispositivo enviar información sobre las pistas que escuchas al servidor de música. Esta información ayuda a crear recomendaciones personalizadas basadas en tus gustos musicales.</string>
|
||||||
<string name="settings_sync_starred_tracks_for_offline_use_title">Sincronizar pistas destacadas para uso sin conexión</string>
|
<string name="settings_sync_starred_tracks_for_offline_use_title">Sincronizar pistas destacadas para uso sin conexión</string>
|
||||||
<string name="settings_theme">Tema</string>
|
<string name="settings_theme">Tema</string>
|
||||||
|
<string name="settings_tile_size">Tamaño de los elementos de la cuadrícula</string>
|
||||||
<string name="settings_title_data">Datos</string>
|
<string name="settings_title_data">Datos</string>
|
||||||
<string name="settings_title_general">General</string>
|
<string name="settings_title_general">General</string>
|
||||||
<string name="settings_title_playlist">Lista de reproducción</string>
|
<string name="settings_title_playlist">Lista de reproducción</string>
|
||||||
@@ -419,6 +427,7 @@
|
|||||||
<string name="share_update_dialog_title">Compartir</string>
|
<string name="share_update_dialog_title">Compartir</string>
|
||||||
<string name="song_bottom_sheet_rate">Valorar</string>
|
<string name="song_bottom_sheet_rate">Valorar</string>
|
||||||
<string name="song_bottom_sheet_remove">Eliminar</string>
|
<string name="song_bottom_sheet_remove">Eliminar</string>
|
||||||
|
<string name="song_bottom_sheet_remove_from_playlist">Eliminar de la lista</string>
|
||||||
<string name="song_bottom_sheet_share">Compartir</string>
|
<string name="song_bottom_sheet_share">Compartir</string>
|
||||||
<string name="song_subtitle_formatter">%1$s • %2$s %3$s</string>
|
<string name="song_subtitle_formatter">%1$s • %2$s %3$s</string>
|
||||||
<string name="starred_sync_dialog_negative_button">Cancelar</string>
|
<string name="starred_sync_dialog_negative_button">Cancelar</string>
|
||||||
@@ -499,6 +508,7 @@
|
|||||||
<string name="settings_github_update_summary">Si se usa la versión de GitHub, la app comprobará nuevas actualizaciones del APK.</string>
|
<string name="settings_github_update_summary">Si se usa la versión de GitHub, la app comprobará nuevas actualizaciones del APK.</string>
|
||||||
<string name="settings_support_summary">Participa en las discusiones y el soporte de la comunidad</string>
|
<string name="settings_support_summary">Participa en las discusiones y el soporte de la comunidad</string>
|
||||||
<string name="settings_show_mini_shuffle_button">Mostrar el botón «Aleatorio»</string>
|
<string name="settings_show_mini_shuffle_button">Mostrar el botón «Aleatorio»</string>
|
||||||
|
<string name="settings_hide_bottom_navbar_on_portrait_summary">Experimental. Aumenta el espacio vertical eliminando la barra de navegación inferior. Los cambios se aplicarán al reiniciar la app.</string>
|
||||||
<string name="settings_auto_download_lyrics">Descargar automáticamente las letras</string>
|
<string name="settings_auto_download_lyrics">Descargar automáticamente las letras</string>
|
||||||
<string name="starred_artist_sync_dialog_summary">Descargar los artistas destacados podría consumir una gran cantidad de datos.</string>
|
<string name="starred_artist_sync_dialog_summary">Descargar los artistas destacados podría consumir una gran cantidad de datos.</string>
|
||||||
<string name="settings_summary_landscape_items_per_row">Aplica a todos los listados de álbumes y artistas. Por defecto es 4</string>
|
<string name="settings_summary_landscape_items_per_row">Aplica a todos los listados de álbumes y artistas. Por defecto es 4</string>
|
||||||
@@ -536,4 +546,33 @@
|
|||||||
<string name="settings_ping_timeout_title">Tiempo de espera de ping al servidor</string>
|
<string name="settings_ping_timeout_title">Tiempo de espera de ping al servidor</string>
|
||||||
<string name="playback_speed_dialog_title">Velocidad de reproducción</string>
|
<string name="playback_speed_dialog_title">Velocidad de reproducción</string>
|
||||||
<string name="settings_title_ui_landscape_items_per_row">Elementos por fila en modo horizontal</string>
|
<string name="settings_title_ui_landscape_items_per_row">Elementos por fila en modo horizontal</string>
|
||||||
|
<string name="aa_albums">Álbumes</string>
|
||||||
|
<string name="aa_album_most_played">Álbumes más reproducidos</string>
|
||||||
|
<string name="aa_album_recently_added">Álbumes añadidos</string>
|
||||||
|
<string name="aa_artists">Artistas</string>
|
||||||
|
<string name="aa_home">Inicio</string>
|
||||||
|
<string name="aa_made_for_you">Para ti</string>
|
||||||
|
<string name="aa_more">Más</string>
|
||||||
|
<string name="aa_music_folder">Carpeta</string>
|
||||||
|
<string name="aa_playlists">Listas de reproducción</string>
|
||||||
|
<string name="aa_podcast">Pódcasts</string>
|
||||||
|
<string name="aa_radio">Radio</string>
|
||||||
|
<string name="aa_random">Aleatorio</string>
|
||||||
|
<string name="aa_recent_albums">Reciente</string>
|
||||||
|
<string name="aa_song_recently_played">Última canción reproducida</string>
|
||||||
|
<string name="aa_starred_albums">★ Álbumes</string>
|
||||||
|
<string name="aa_starred_artists">★ Artistas</string>
|
||||||
|
<string name="playlist_chooser_dialog_toast_remove_success">Canción eliminada de la lista</string>
|
||||||
|
<string name="settings_androidauto">Android Auto</string>
|
||||||
|
<string name="settings_androidauto_album_view">Vista de cuadrícula para álbumes</string>
|
||||||
|
<string name="settings_androidauto_home_view">Vista de cuadrícula para la página de inicio</string>
|
||||||
|
<string name="settings_androidauto_playlist_view">Vista de cuadrícula para listas de reproducción</string>
|
||||||
|
<string name="settings_androidauto_podcast_view">Vista de cuadrícula para pódcasts</string>
|
||||||
|
<string name="settings_androidauto_radio_view">Vista de cuadrícula para emisoras de radio</string>
|
||||||
|
<string name="settings_androidauto_first_tab">Vista de la primera pestaña</string>
|
||||||
|
<string name="settings_androidauto_second_tab">Vista de la segunda pestaña</string>
|
||||||
|
<string name="settings_androidauto_third_tab">Vista de la tercera pestaña</string>
|
||||||
|
<string name="settings_enable_drawer_on_landscape">Habilitar el menú lateral en modo vertical [Experimental]</string>
|
||||||
|
<string name="settings_enable_drawer_on_landscape_summary">Desbloquea el menú lateral horizontal en modo vertical. Los cambios se aplicarán al reiniciar la app.</string>
|
||||||
|
<string name="settings_hide_bottom_navbar_on_portrait">Ocultar la barra de navegación inferior en modo vertical [Experimental]</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -255,6 +255,20 @@
|
|||||||
<item>4</item>
|
<item>4</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="tile_size_titles">
|
||||||
|
<item>Minuscule</item>
|
||||||
|
<item>Petite</item>
|
||||||
|
<item>Moyenne</item>
|
||||||
|
<item>Large</item>
|
||||||
|
<item>Défaut</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="tile_size_divisor">
|
||||||
|
<item>6</item>
|
||||||
|
<item>5</item>
|
||||||
|
<item>4</item>
|
||||||
|
<item>3</item>
|
||||||
|
<item>2</item>
|
||||||
|
</string-array>
|
||||||
<!-- Add by MFO -->
|
<!-- Add by MFO -->
|
||||||
<string-array name="aa_tab_titles">
|
<string-array name="aa_tab_titles">
|
||||||
<item>Ne pas afficher</item>
|
<item>Ne pas afficher</item>
|
||||||
@@ -274,6 +288,7 @@
|
|||||||
<item>Albums favoris</item>
|
<item>Albums favoris</item>
|
||||||
<item>Artistes favoris</item>
|
<item>Artistes favoris</item>
|
||||||
<item>Aléatoire</item>
|
<item>Aléatoire</item>
|
||||||
|
<item>Genres</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="aa_tab_values">
|
<string-array name="aa_tab_values">
|
||||||
<item>-1</item>
|
<item>-1</item>
|
||||||
@@ -293,6 +308,7 @@
|
|||||||
<item>13</item>
|
<item>13</item>
|
||||||
<item>14</item>
|
<item>14</item>
|
||||||
<item>15</item>
|
<item>15</item>
|
||||||
|
<item>16</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<!-- end Add by MFO -->
|
<!-- end Add by MFO -->
|
||||||
|
|
||||||
|
|||||||
@@ -338,6 +338,8 @@
|
|||||||
<string name="settings_androidauto_second_tab">Affichage du deuxième onglet</string>
|
<string name="settings_androidauto_second_tab">Affichage du deuxième onglet</string>
|
||||||
<string name="settings_androidauto_third_tab">Affichage du troisième onglet</string>
|
<string name="settings_androidauto_third_tab">Affichage du troisième onglet</string>
|
||||||
<string name="settings_androidauto_fourth_tab">Affichage du quatrième onglet</string>
|
<string name="settings_androidauto_fourth_tab">Affichage du quatrième onglet</string>
|
||||||
|
<string name="settings_androidauto_shuffle_genre_songs">Mélanger les chansons par genre</string>
|
||||||
|
<string name="settings_androidauto_shuffle_genre_songs_summary">Lire des chansons aléatoires lors de la sélection d\'un genre</string>
|
||||||
<string name="settings_audio_transcode_download_format">Format de transcodage</string>
|
<string name="settings_audio_transcode_download_format">Format de transcodage</string>
|
||||||
<string name="settings_audio_transcode_download_priority_summary">Si activé, Tempus ne forcera pas le téléchargement de la piste avec les paramètres de transcodage ci-dessous.</string>
|
<string name="settings_audio_transcode_download_priority_summary">Si activé, Tempus ne forcera pas le téléchargement de la piste avec les paramètres de transcodage ci-dessous.</string>
|
||||||
<string name="settings_audio_transcode_download_priority_title">Prioriser les paramètres du serveurs, utilisés pour le streaming, dans les téléchargements</string>
|
<string name="settings_audio_transcode_download_priority_title">Prioriser les paramètres du serveurs, utilisés pour le streaming, dans les téléchargements</string>
|
||||||
@@ -432,7 +434,8 @@
|
|||||||
<string name="settings_sync_starred_tracks_for_offline_use_summary">Si activé, les pistes favorites seront téléchargées pour l\'écoute hors-ligne.</string>
|
<string name="settings_sync_starred_tracks_for_offline_use_summary">Si activé, les pistes favorites seront téléchargées pour l\'écoute hors-ligne.</string>
|
||||||
<string name="settings_sync_starred_tracks_for_offline_use_title">Synchronisation des pistes favorites pour écoute hors-ligne</string>
|
<string name="settings_sync_starred_tracks_for_offline_use_title">Synchronisation des pistes favorites pour écoute hors-ligne</string>
|
||||||
<string name="settings_theme">Thème</string>
|
<string name="settings_theme">Thème</string>
|
||||||
<string name="settings_title_data">Données</string>
|
<string name="settings_tile_size">Taille des vignettes</string>
|
||||||
|
<string name="settings_title_data">Données</string>
|
||||||
<string name="settings_title_general">Géneral</string>
|
<string name="settings_title_general">Géneral</string>
|
||||||
<string name="settings_title_playlist">Playlist</string>
|
<string name="settings_title_playlist">Playlist</string>
|
||||||
<string name="settings_title_rating">Note</string>
|
<string name="settings_title_rating">Note</string>
|
||||||
|
|||||||
@@ -277,4 +277,57 @@
|
|||||||
<item>6</item>
|
<item>6</item>
|
||||||
<item>7</item>
|
<item>7</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="tile_size_titles">
|
||||||
|
<item>Bardzo mały</item>
|
||||||
|
<item>Mały</item>
|
||||||
|
<item>Średni</item>
|
||||||
|
<item>Duży</item>
|
||||||
|
<item>Domyślny</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="tile_size_divisor">
|
||||||
|
<item>6</item>
|
||||||
|
<item>5</item>
|
||||||
|
<item>4</item>
|
||||||
|
<item>3</item>
|
||||||
|
<item>2</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="aa_tab_titles">
|
||||||
|
<item>Nie wyświetlaj</item>
|
||||||
|
<item>Strona główna</item>
|
||||||
|
<item>Ostatnie</item>
|
||||||
|
<item>Albumy</item>
|
||||||
|
<item>Wykonawcy</item>
|
||||||
|
<item>Playlisty</item>
|
||||||
|
<item>Podcasty</item>
|
||||||
|
<item>Radio</item>
|
||||||
|
<item>Foldery</item>
|
||||||
|
<item>Najczęściej odtwarzane albumy</item>
|
||||||
|
<item>Dodane albumy</item>
|
||||||
|
<item>Utwory oznaczone gwiazdką</item>
|
||||||
|
<item>Albumy oznaczone gwiazdką</item>
|
||||||
|
<item>Wykonawcy oznaczeni gwiazdką</item>
|
||||||
|
<item>Losowe</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="aa_tab_values">
|
||||||
|
<item>-1</item>
|
||||||
|
<item>0</item>
|
||||||
|
<item>1</item>
|
||||||
|
<item>2</item>
|
||||||
|
<item>3</item>
|
||||||
|
<item>4</item>
|
||||||
|
<item>5</item>
|
||||||
|
<item>6</item>
|
||||||
|
<item>7</item>
|
||||||
|
<item>8</item>
|
||||||
|
<item>9</item>
|
||||||
|
<item>10</item>
|
||||||
|
<item>11</item>
|
||||||
|
<item>12</item>
|
||||||
|
<item>13</item>
|
||||||
|
<item>14</item>
|
||||||
|
<item>15</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -1,4 +1,21 @@
|
|||||||
<resources>
|
<resources>
|
||||||
|
<string name="aa_albums">Albumy</string>
|
||||||
|
<string name="aa_album_most_played">Najczęściej odtwarzane albumy</string>
|
||||||
|
<string name="aa_album_recently_added">Dodane albumy</string>
|
||||||
|
<string name="aa_artists">Wykonawcy</string>
|
||||||
|
<string name="aa_home">Strona główna</string>
|
||||||
|
<string name="aa_made_for_you">Dla ciebie</string>
|
||||||
|
<string name="aa_more">Więcej</string>
|
||||||
|
<string name="aa_music_folder">Foldery</string>
|
||||||
|
<string name="aa_playlists">Playlisty</string>
|
||||||
|
<string name="aa_podcast">Podcasty</string>
|
||||||
|
<string name="aa_radio">Radio</string>
|
||||||
|
<string name="aa_random">Losowe</string>
|
||||||
|
<string name="aa_recent_albums">Ostatnie</string>
|
||||||
|
<string name="aa_song_recently_played">Odtwarzane piosenki</string>
|
||||||
|
<string name="aa_starred_albums">★ Albumy</string>
|
||||||
|
<string name="aa_starred_artists">★ Wykonawcy</string>
|
||||||
|
<string name="aa_starred_tracks">★ Utwory</string>
|
||||||
<string name="activity_battery_optimizations_conclusion">Jeżeli masz problemy odwiedź stronę https://dontkillmyapp.com. Podaje ona dokładne instrukcje na temat tego jak wyłączyć funkcje oszczędzania energii które mogą wpływać na wydajność aplikacji.</string>
|
<string name="activity_battery_optimizations_conclusion">Jeżeli masz problemy odwiedź stronę https://dontkillmyapp.com. Podaje ona dokładne instrukcje na temat tego jak wyłączyć funkcje oszczędzania energii które mogą wpływać na wydajność aplikacji.</string>
|
||||||
<string name="activity_battery_optimizations_summary">Wyłącz optymalizacje baterii aby odtwarzać media przy wyłączonym ekranie.</string>
|
<string name="activity_battery_optimizations_summary">Wyłącz optymalizacje baterii aby odtwarzać media przy wyłączonym ekranie.</string>
|
||||||
<string name="activity_battery_optimizations_title">Optymalizcje Baterii</string>
|
<string name="activity_battery_optimizations_title">Optymalizcje Baterii</string>
|
||||||
@@ -362,6 +379,16 @@
|
|||||||
<string name="settings_podcast">Pokazuj podcasty</string>
|
<string name="settings_podcast">Pokazuj podcasty</string>
|
||||||
<string name="settings_podcast_summary">Jeżeli włączone, widoczna będzie sekcja z podcastami. Zrestartuj aplikację aby, zmiany przyniosły pełny efekt.</string>
|
<string name="settings_podcast_summary">Jeżeli włączone, widoczna będzie sekcja z podcastami. Zrestartuj aplikację aby, zmiany przyniosły pełny efekt.</string>
|
||||||
<string name="settings_playlist_sort">Sortowanie playlist</string>
|
<string name="settings_playlist_sort">Sortowanie playlist</string>
|
||||||
|
<string name="settings_androidauto">Android Auto</string>
|
||||||
|
<string name="settings_androidauto_album_view">Układ siatki dla albumów</string>
|
||||||
|
<string name="settings_androidauto_home_view">Układ siatki dla strony głównej</string>
|
||||||
|
<string name="settings_androidauto_playlist_view">Układ siatki dla playlist</string>
|
||||||
|
<string name="settings_androidauto_podcast_view">Układ siatki dla podcastów</string>
|
||||||
|
<string name="settings_androidauto_radio_view">Układ siatki dla radia</string>
|
||||||
|
<string name="settings_androidauto_first_tab">Pierwsza zakładka</string>
|
||||||
|
<string name="settings_androidauto_second_tab">Druga zakładka</string>
|
||||||
|
<string name="settings_androidauto_third_tab">Trzecia zakładka</string>
|
||||||
|
<string name="settings_androidauto_fourth_tab">Czwarta zakładka</string>
|
||||||
<string name="settings_audio_quality">Pokaż jakość audio</string>
|
<string name="settings_audio_quality">Pokaż jakość audio</string>
|
||||||
<string name="settings_audio_quality_summary">Bitrate i format audio będzie pokazywany dla każdego utworu.</string>
|
<string name="settings_audio_quality_summary">Bitrate i format audio będzie pokazywany dla każdego utworu.</string>
|
||||||
<string name="settings_song_rating">Pokaż ocenę piosenek w gwiazdkach</string>
|
<string name="settings_song_rating">Pokaż ocenę piosenek w gwiazdkach</string>
|
||||||
@@ -410,6 +437,7 @@
|
|||||||
<string name="settings_sync_starred_tracks_for_offline_use_summary">Jeżeli włączone, utwory oznaczone gwiazdką będą pobrane do użycia offline.</string>
|
<string name="settings_sync_starred_tracks_for_offline_use_summary">Jeżeli włączone, utwory oznaczone gwiazdką będą pobrane do użycia offline.</string>
|
||||||
<string name="settings_sync_starred_tracks_for_offline_use_title">Zsynchronizuj utwory oznaczone gwiazdką do użycia offline</string>
|
<string name="settings_sync_starred_tracks_for_offline_use_title">Zsynchronizuj utwory oznaczone gwiazdką do użycia offline</string>
|
||||||
<string name="settings_theme">Motyw</string>
|
<string name="settings_theme">Motyw</string>
|
||||||
|
<string name="settings_tile_size">Rozmiar kafelków</string>
|
||||||
<string name="settings_title_data">Dane</string>
|
<string name="settings_title_data">Dane</string>
|
||||||
<string name="settings_title_general">Ogólne</string>
|
<string name="settings_title_general">Ogólne</string>
|
||||||
<string name="settings_title_playlist">Playlisty</string>
|
<string name="settings_title_playlist">Playlisty</string>
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string-array name="theme_list_titles">
|
<string-array name="theme_list_titles">
|
||||||
<item>Светлый</item>
|
<item>Светлая</item>
|
||||||
<item>Темный</item>
|
<item>Темная</item>
|
||||||
<item>Системный по умолчанию</item>
|
<item>Системная по умолчанию</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="theme_list_values">
|
<string-array name="theme_list_values">
|
||||||
<item>светлый</item>
|
<item>light</item>
|
||||||
<item>темный</item>
|
<item>dark</item>
|
||||||
<item>по умолчанию</item>
|
<item>default</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="pref_cache_size_titles">
|
<string-array name="pref_cache_size_titles">
|
||||||
<item>Высокий</item>
|
<item>Большой</item>
|
||||||
<item>Средний</item>
|
<item>Средний</item>
|
||||||
<item>Низкий</item>
|
<item>Маленький</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="pref_cache_size_values">
|
<string-array name="pref_cache_size_values">
|
||||||
<item>500</item>
|
<item>500</item>
|
||||||
@@ -22,9 +22,9 @@
|
|||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="pref_image_size_titles">
|
<string-array name="pref_image_size_titles">
|
||||||
<item>Высокий</item>
|
<item>Высокое</item>
|
||||||
<item>Средний</item>
|
<item>Среднее</item>
|
||||||
<item>Низкий</item>
|
<item>Низкое</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="pref_image_size_values">
|
<string-array name="pref_image_size_values">
|
||||||
<item>-1</item>
|
<item>-1</item>
|
||||||
@@ -165,7 +165,7 @@
|
|||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="audio_transcode_format_download_list_titles">
|
<string-array name="audio_transcode_format_download_list_titles">
|
||||||
<item>Прямая загрузка</item>
|
<item>Оригинал</item>
|
||||||
<item>Opus</item>
|
<item>Opus</item>
|
||||||
<item>AAC</item>
|
<item>AAC</item>
|
||||||
<item>Mp3</item>
|
<item>Mp3</item>
|
||||||
@@ -191,9 +191,9 @@
|
|||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="rounded_corner_size_titles">
|
<string-array name="rounded_corner_size_titles">
|
||||||
<item>Высокий</item>
|
<item>Сильное скругление</item>
|
||||||
<item>Средний</item>
|
<item>Среднее скругление</item>
|
||||||
<item>Низкий</item>
|
<item>Небольшое скругление</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="rounded_corner_size_values">
|
<string-array name="rounded_corner_size_values">
|
||||||
<item>18</item>
|
<item>18</item>
|
||||||
@@ -202,23 +202,23 @@
|
|||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="replay_gain_titles">
|
<string-array name="replay_gain_titles">
|
||||||
<item>Отключенный</item>
|
<item>Выключено</item>
|
||||||
<item>Трек</item>
|
<item>Трек</item>
|
||||||
<item>Альбом</item>
|
<item>Альбом</item>
|
||||||
<item>Авто</item>
|
<item>Авто</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="replay_gain_values">
|
<string-array name="replay_gain_values">
|
||||||
<item>отключенный</item>
|
<item>disabled</item>
|
||||||
<item>трек</item>
|
<item>track</item>
|
||||||
<item>альбом</item>
|
<item>album</item>
|
||||||
<item>авто</item>
|
<item>auto</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="transcoded_download_option_list_titles">
|
<string-array name="transcoded_download_option_list_titles">
|
||||||
<item>Не перекодировать</item>
|
<item>Не транскодировать</item>
|
||||||
<item>Настройки сервера</item>
|
<item>Настройки сервера</item>
|
||||||
<item>Формат транскодирования Wi-Fi</item>
|
<item>Формат транскодирования Wi-Fi</item>
|
||||||
<item>Формат мобильного транскодирования</item>
|
<item>Формат транскодирования моб. сети</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="transcoded_download_option_list_values">
|
<string-array name="transcoded_download_option_list_values">
|
||||||
<item>0</item>
|
<item>0</item>
|
||||||
@@ -229,9 +229,9 @@
|
|||||||
|
|
||||||
<string-array name="buffering_strategy_titles">
|
<string-array name="buffering_strategy_titles">
|
||||||
<item>Минимум</item>
|
<item>Минимум</item>
|
||||||
<item>Умеренный</item>
|
<item>Умеренно</item>
|
||||||
<item>Агрессивный</item>
|
<item>Агрессивно</item>
|
||||||
<item>Экстремальный</item>
|
<item>Экстремально</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="buffering_strategy_values">
|
<string-array name="buffering_strategy_values">
|
||||||
<item>.1</item>
|
<item>.1</item>
|
||||||
@@ -240,6 +240,15 @@
|
|||||||
<item>8</item>
|
<item>8</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="playlist_sort_option_titles">
|
||||||
|
<item>По названию</item>
|
||||||
|
<item>Случайно</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="playlist_sort_option_values">
|
||||||
|
<item>ORDER_BY_NAME</item>
|
||||||
|
<item>ORDER_BY_RANDOM</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
<string-array name="skip_min_star_rating_titles">
|
<string-array name="skip_min_star_rating_titles">
|
||||||
<item>0 звезд минимум</item>
|
<item>0 звезд минимум</item>
|
||||||
<item>1 звезда минимум</item>
|
<item>1 звезда минимум</item>
|
||||||
@@ -254,4 +263,62 @@
|
|||||||
<item>3</item>
|
<item>3</item>
|
||||||
<item>4</item>
|
<item>4</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
<string-array name="landscape_items_per_row">
|
||||||
|
<item>3"</item>
|
||||||
|
<item>4</item>
|
||||||
|
<item>5</item>
|
||||||
|
<item>6</item>
|
||||||
|
<item>7</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="landscape_items_per_row_values">
|
||||||
|
<item>3</item>
|
||||||
|
<item>4</item>
|
||||||
|
<item>5</item>
|
||||||
|
<item>6</item>
|
||||||
|
<item>7</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<!-- Add by MFO -->
|
||||||
|
<string-array name="aa_tab_titles">
|
||||||
|
<item>Не показывать</item>
|
||||||
|
<item>Главная</item>
|
||||||
|
<item>Недавние</item>
|
||||||
|
<item>Альбомы</item>
|
||||||
|
<item>Артисты</item>
|
||||||
|
<item>Плейлисты</item>
|
||||||
|
<item>Подкасты</item>
|
||||||
|
<item>Радио</item>
|
||||||
|
<item>Папки</item>
|
||||||
|
<item>Популярные альбомы</item>
|
||||||
|
<!-- <item>Tracks played</item> -->
|
||||||
|
<item>Недавно добавленные альбомы</item>
|
||||||
|
<!-- <item>For you</item> -->
|
||||||
|
<item>Избранные треки</item>
|
||||||
|
<item>Избранные альбомы</item>
|
||||||
|
<item>Избранные артисты</item>
|
||||||
|
<item>Случайное</item>
|
||||||
|
<item>Жанры</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="aa_tab_values">
|
||||||
|
<item>-1</item>
|
||||||
|
<item>0</item>
|
||||||
|
<item>1</item>
|
||||||
|
<item>2</item>
|
||||||
|
<item>3</item>
|
||||||
|
<item>4</item>
|
||||||
|
<item>5</item>
|
||||||
|
<item>6</item>
|
||||||
|
<item>7</item>
|
||||||
|
<item>8</item>
|
||||||
|
<item>9</item>
|
||||||
|
<item>10</item>
|
||||||
|
<item>11</item>
|
||||||
|
<item>12</item>
|
||||||
|
<item>13</item>
|
||||||
|
<item>14</item>
|
||||||
|
<item>15</item>
|
||||||
|
<item>16</item>
|
||||||
|
</string-array>
|
||||||
|
<!-- end Add by MFO -->
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -1,161 +1,204 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="activity_battery_optimizations_conclusion">Если у вас возникли проблемы, посетите https://dontkillmyapp.com. Он содержит подробные инструкции о том, как отключить любые функции энергосбережения, которые могут повлиять на производительность приложения.</string>
|
<string name="aa_albums">Альбомы</string>
|
||||||
|
<string name="aa_album_most_played">Популярные альбомы</string>
|
||||||
|
<string name="aa_album_recently_added">Добавленные альбомы</string>
|
||||||
|
<string name="aa_artists">Артисты</string>
|
||||||
|
<string name="aa_home">Главная</string>
|
||||||
|
<string name="aa_made_for_you">Персональная подборка</string>
|
||||||
|
<string name="aa_more">Еще</string>
|
||||||
|
<string name="aa_music_folder">Папка</string>
|
||||||
|
<string name="aa_playlists">Плейлисты</string>
|
||||||
|
<string name="aa_podcast">Подкасты</string>
|
||||||
|
<string name="aa_radio">Радио</string>
|
||||||
|
<string name="aa_random">Случайное</string>
|
||||||
|
<string name="aa_recent_albums">Недавние</string>
|
||||||
|
<string name="aa_song_recently_played">Недавно воспроизведенные</string>
|
||||||
|
<string name="aa_starred_albums">★ Альбомы</string>
|
||||||
|
<string name="aa_starred_artists">★ Артисты</string>
|
||||||
|
<string name="aa_starred_tracks">★ Треки</string>
|
||||||
|
|
||||||
|
<string name="activity_battery_optimizations_conclusion">Если возникают проблемы, посетите https://dontkillmyapp.com. Сайт содержит инструкции по отключению функций энергосбережения, которые могут влиять на работу приложения.</string>
|
||||||
<string name="activity_battery_optimizations_summary">Пожалуйста, отключите оптимизацию батареи для воспроизведения мультимедиа при выключенном экране.</string>
|
<string name="activity_battery_optimizations_summary">Пожалуйста, отключите оптимизацию батареи для воспроизведения мультимедиа при выключенном экране.</string>
|
||||||
<string name="activity_battery_optimizations_title">Оптимизация батареи</string>
|
<string name="activity_battery_optimizations_title">Оптимизация батареи</string>
|
||||||
<string name="activity_info_offline_mode">Автономный режим</string>
|
<string name="activity_info_offline_mode">Офлайн-режим</string>
|
||||||
<string name="album_bottom_sheet_add_to_playlist">Добавить в плейлист</string>
|
<string name="album_bottom_sheet_add_to_playlist">Добавить в плейлист</string>
|
||||||
<string name="album_bottom_sheet_add_to_queue">Добавить в очередь</string>
|
<string name="album_bottom_sheet_add_to_queue">Добавить в очередь</string>
|
||||||
<string name="album_bottom_sheet_download_all">Скачать все</string>
|
<string name="album_bottom_sheet_download_all">Скачать все</string>
|
||||||
<string name="album_bottom_sheet_go_to_artist">Перейти к исполнителю</string>
|
<string name="album_bottom_sheet_go_to_artist">Перейти к исполнителю</string>
|
||||||
<string name="album_bottom_sheet_instant_mix">Мгновенный микс</string>
|
<string name="album_bottom_sheet_instant_mix">Мгновенный микс</string>
|
||||||
<string name="album_bottom_sheet_play_next">Играть дальше</string>
|
<string name="album_bottom_sheet_play_next">Играть следующим</string>
|
||||||
<string name="album_bottom_sheet_remove_all">Убрать все</string>
|
<string name="album_bottom_sheet_remove_all">Убрать все</string>
|
||||||
<string name="album_bottom_sheet_share">Поделиться</string>
|
<string name="album_bottom_sheet_share">Поделиться</string>
|
||||||
<string name="album_bottom_sheet_shuffle">Перемешать</string>
|
<string name="album_bottom_sheet_shuffle">Перемешать</string>
|
||||||
<string name="album_catalogue_title">Альбомы</string>
|
<string name="album_catalogue_title">Альбомы</string>
|
||||||
<string name="album_catalogue_title_expanded">Просмотр альбомов</string>
|
<string name="album_catalogue_title_expanded">Обзор альбомов</string>
|
||||||
<string name="album_error_retrieving_artist">Не удалось получить исполнителя.</string>
|
<string name="album_error_retrieving_artist">Не удалось получить исполнителя</string>
|
||||||
<string name="album_list_page_downloaded">Скачанные альбомы</string>
|
<string name="album_list_page_downloaded">Скачанные альбомы</string>
|
||||||
<string name="album_list_page_most_played">Самые проигрываемые альбомы</string>
|
<string name="album_list_page_most_played">Самые проигрываемые альбомы</string>
|
||||||
<string name="album_list_page_new_releases">Новые релизы</string>
|
<string name="album_list_page_new_releases">Новые релизы</string>
|
||||||
<string name="album_list_page_recently_added">Недавно добавленные альбомы</string>
|
<string name="album_list_page_recently_added">Недавно добавленные альбомы</string>
|
||||||
<string name="album_list_page_recently_played">Недавно воспроизведенные альбомы</string>
|
<string name="album_list_page_recently_played">Недавно воспроизведенные альбомы</string>
|
||||||
<string name="album_list_page_starred">Помеченные альбомы</string>
|
<string name="album_list_page_starred">Избранные альбомы</string>
|
||||||
<string name="album_list_page_title">Альбомы</string>
|
<string name="album_list_page_title">Альбомы</string>
|
||||||
<string name="album_page_extra_info_button">Больше подобного</string>
|
<string name="album_page_extra_info_button">Больше подобного</string>
|
||||||
<string name="album_page_play_button">Играть</string>
|
<string name="album_page_play_button">Играть</string>
|
||||||
<string name="album_page_release_date_label">Выпущен %1$s</string>
|
<string name="album_page_release_date_label">Дата релиза: %1$s</string>
|
||||||
<string name="album_page_release_dates_label">Выпущен %1$s, оригинал %2$s</string>
|
<string name="album_page_release_dates_label">Дата релиза: %1$s, оригинал %2$s</string>
|
||||||
<string name="album_page_shuffle_button">Смешать</string>
|
<string name="album_page_shuffle_button">Перемешать</string>
|
||||||
<string name="album_page_tracks_count_and_duration">%1$d треков • %2$d минут</string>
|
<string name="album_page_tracks_count_and_duration">%1$d треков • %2$d минут(ы)</string>
|
||||||
<string name="app_name">Tempus</string>
|
<string name="app_name">Tempus</string>
|
||||||
<string name="artist_adapter_radio_station_starting">Поиск…</string>
|
<string name="artist_adapter_radio_station_starting">Поиск…</string>
|
||||||
<string name="artist_bottom_sheet_instant_mix">Мгновенный микс</string>
|
<string name="artist_bottom_sheet_instant_mix">Мгновенный микс</string>
|
||||||
<string name="artist_bottom_sheet_shuffle">Смешать</string>
|
<string name="artist_bottom_sheet_shuffle">Перемешать</string>
|
||||||
<string name="artist_catalogue_title">Артисты</string>
|
<string name="artist_catalogue_title">Исполнители</string>
|
||||||
<string name="artist_catalogue_title_expanded">Просмотр исполнителя</string>
|
<string name="artist_catalogue_title_expanded">Обзор исполнителей</string>
|
||||||
<string name="artist_error_retrieving_radio">Ошибка при получении радио исполнителя.</string>
|
<string name="artist_error_retrieving_radio">Ошибка при получении радио исполнителя</string>
|
||||||
<string name="artist_error_retrieving_tracks">Ошибка при получении треков исполнителя.</string>
|
<string name="artist_error_retrieving_tracks">Ошибка при получении треков исполнителя</string>
|
||||||
<string name="artist_list_page_downloaded">Скачанные исполнители</string>
|
<string name="artist_list_page_downloaded">Скачанные исполнители</string>
|
||||||
<string name="artist_list_page_starred">Рейтинговые исполнители</string>
|
<string name="artist_list_page_starred">Избранные исполнители</string>
|
||||||
<string name="artist_list_page_title">Исполнители</string>
|
<string name="artist_list_page_title">Исполнители</string>
|
||||||
|
<string name="artist_no_artist_info_toast">Нет данных об исполнителе</string>
|
||||||
<string name="artist_page_radio_button">Радио</string>
|
<string name="artist_page_radio_button">Радио</string>
|
||||||
<string name="artist_page_shuffle_button">Смешать</string>
|
<string name="artist_page_shuffle_button">Смешать</string>
|
||||||
<string name="artist_page_switch_layout_button">Переключить раскладку</string>
|
<string name="artist_page_switch_layout_button">Сменить вид</string>
|
||||||
<string name="artist_page_title_album_more_like_this_button">Больше подобного</string>
|
<string name="artist_page_title_album_more_like_this_button">Больше подобного</string>
|
||||||
<string name="artist_page_title_album_section">Альбомы</string>
|
<string name="artist_page_title_album_section">Альбомы</string>
|
||||||
<string name="artist_page_title_biography_more_button">Больше</string>
|
<string name="artist_page_title_biography_more_button">Больше</string>
|
||||||
<string name="artist_page_title_biography_section">Биография</string>
|
<string name="artist_page_title_biography_section">Биография</string>
|
||||||
<string name="artist_page_title_most_streamed_song_section">Самые прослушиваемые треки</string>
|
<string name="artist_page_title_most_streamed_song_section">Самые популярные треки</string>
|
||||||
<string name="artist_page_title_most_streamed_song_see_all_button">Посмотреть все</string>
|
<string name="artist_page_title_most_streamed_song_see_all_button">Все</string>
|
||||||
<string name="battery_optimization_negative_button">Игнорировать</string>
|
<string name="battery_optimization_negative_button">Игнорировать</string>
|
||||||
<string name="battery_optimization_neutral_button">Больше не спрашивать</string>
|
<string name="battery_optimization_neutral_button">Больше не спрашивать</string>
|
||||||
<string name="battery_optimization_positive_button">Отключить</string>
|
<string name="battery_optimization_positive_button">Отключить</string>
|
||||||
|
<string name="bottom_sheet_generating_instant_mix">Создания мгновенного микса...</string>
|
||||||
|
<string name="bottom_sheet_problem_generating_instant_mix">Не удалось получить треки с сервера Subsonic.</string>
|
||||||
<string name="connection_alert_dialog_negative_button">Отмена</string>
|
<string name="connection_alert_dialog_negative_button">Отмена</string>
|
||||||
<string name="connection_alert_dialog_neutral_button">Включить сохранение данных</string>
|
<string name="connection_alert_dialog_neutral_button">Включить экономию данных</string>
|
||||||
<string name="connection_alert_dialog_positive_button">OK</string>
|
<string name="connection_alert_dialog_positive_button">OK</string>
|
||||||
<string name="connection_alert_dialog_summary">Доступ к серверу Subsonic по соединениям, отличным от Wi-Fi, ограничен. Чтобы это диалоговое окно предупреждения не появлялось снова, отключите проверку соединения в настройках приложения.</string>
|
<string name="connection_alert_dialog_summary">Доступ к серверу Subsonic по соединениям, отличным от Wi-Fi, ограничен. Чтобы это окно больше не появлялось, отключите проверку соединения в настройках приложения.</string>
|
||||||
<string name="connection_alert_dialog_title">Wi-Fi не подключен</string>
|
<string name="connection_alert_dialog_title">Wi-Fi не подключен</string>
|
||||||
<string name="content_description_shuffle_button">Перемешать</string>
|
<string name="content_description_shuffle_button">Перемешать</string>
|
||||||
<string name="delete_download_storage_dialog_negative_button">Отмена</string>
|
<string name="delete_download_storage_dialog_negative_button">Отмена</string>
|
||||||
<string name="delete_download_storage_dialog_positive_button">Продолжить</string>
|
<string name="delete_download_storage_dialog_positive_button">Продолжить</string>
|
||||||
<string name="delete_download_storage_dialog_summary">Имейте в виду, что продолжение этого действия приведет к безвозвратному удалению всех сохраненных элементов, загруженных со всех серверов.</string>
|
<string name="delete_download_storage_dialog_summary">Обратите внимание, что продолжение приведёт к безвозвратному удалению всех сохранённых элементов, загруженных со всех серверов.</string>
|
||||||
<string name="delete_download_storage_dialog_title">Удалить сохраненные элементы</string>
|
<string name="delete_download_storage_dialog_title">Удалить сохраненные элементы</string>
|
||||||
<string name="description_empty_title">Нет описания</string>
|
<string name="description_empty_title">Текст песни недоступен</string>
|
||||||
<string name="disc_titlefull">Диск %1$s - %2$s</string>
|
<string name="disc_titlefull">Диск %1$s - %2$s</string>
|
||||||
<string name="disc_titleless">Диск %1$s</string>
|
<string name="disc_titleless">Диск %1$s</string>
|
||||||
<string name="download_directory_dialog_negative_button">Отмена</string>
|
<string name="download_directory_dialog_negative_button">Отмена</string>
|
||||||
<string name="download_directory_dialog_positive_button">Загрузить</string>
|
<string name="download_directory_dialog_positive_button">Скачать</string>
|
||||||
<string name="download_directory_dialog_summary">Все треки из этой папки будут загружены. Треки, находящиеся в подпапках, не будут загружены.</string>
|
<string name="download_directory_dialog_summary">Все треки из этой папки будут скачаны. Треки в подпапках скачаны не будут.</string>
|
||||||
<string name="download_directory_dialog_title">Скачать треки</string>
|
<string name="download_directory_dialog_title">Скачать треки</string>
|
||||||
<string name="download_info_empty_subtitle">Скачав песню, вы найдете ее здесь.</string>
|
<string name="download_directory_set">Выбрать место скачанной музыки</string>
|
||||||
|
<string name="download_info_empty_subtitle">Скачав песню, вы найдете ее здесь</string>
|
||||||
<string name="download_info_empty_title">Загрузок пока нет!</string>
|
<string name="download_info_empty_title">Загрузок пока нет!</string>
|
||||||
<string name="download_item_multiple_subtitle_formatter">%1$s • %2$s товаров</string>
|
<string name="download_item_multiple_subtitle_formatter">%1$s • %2$s элементов</string>
|
||||||
<string name="download_item_single_subtitle_formatter">%1$s предметов</string>
|
<string name="download_item_single_subtitle_formatter">%1$s элементов</string>
|
||||||
<string name="download_shuffle_all_subtitle">Перемешать все</string>
|
<string name="download_shuffle_all_subtitle">Перемешать все</string>
|
||||||
<string name="download_storage_dialog_sub_summary">Чтобы изменения вступили в силу, перезапустите приложение.</string>
|
<string name="download_storage_dialog_sub_summary">Чтобы изменения вступили в силу, перезапустите приложение.</string>
|
||||||
<string name="download_storage_dialog_summary">Изменение места назначения загружаемых файлов из одного хранилища в другое приведет к немедленному удалению всех ранее загруженных файлов в другом хранилище.</string>
|
<string name="download_storage_dialog_summary">Изменение места хранения загрузок приведёт к немедленному удалению ранее скачанных файлов из старого хранилища.</string>
|
||||||
<string name="download_storage_dialog_title">Выберите вариант хранения</string>
|
<string name="download_storage_dialog_title">Выберите хранилище</string>
|
||||||
<string name="download_storage_external_dialog_positive_button">Внешний</string>
|
<string name="download_storage_external_dialog_positive_button">Внешнее</string>
|
||||||
<string name="download_storage_internal_dialog_negative_button">Внутренний</string>
|
<string name="download_storage_internal_dialog_negative_button">Внутреннее</string>
|
||||||
|
<string name="download_storage_directory_dialog_neutral_button">Директория</string>
|
||||||
<string name="download_title_section">Загрузки</string>
|
<string name="download_title_section">Загрузки</string>
|
||||||
|
<string name="download_refresh_no_directory">Укажите директорию загрузок, чтобы обновить список.</string>
|
||||||
|
<string name="download_refresh_no_changes">Отсутствующие загрузки не найдены.</string>
|
||||||
|
<plurals name="download_refresh_removed">
|
||||||
|
<item quantity="one">Удалена %d отсутствующая загрузка.</item>
|
||||||
|
<item quantity="other">Удалено %d отсутствующих загрузок.</item>
|
||||||
|
</plurals>
|
||||||
|
<string name="download_refresh_button_content_description">Обновить список загрузок</string>
|
||||||
<string name="downloaded_bottom_sheet_add_to_queue">Добавить в очередь</string>
|
<string name="downloaded_bottom_sheet_add_to_queue">Добавить в очередь</string>
|
||||||
<string name="downloaded_bottom_sheet_play_next">Играть дальше</string>
|
<string name="downloaded_bottom_sheet_play_next">Играть следующим</string>
|
||||||
<string name="downloaded_bottom_sheet_remove">Удалить</string>
|
<string name="downloaded_bottom_sheet_remove">Удалить</string>
|
||||||
<string name="downloaded_bottom_sheet_remove_all">Убрать все</string>
|
<string name="downloaded_bottom_sheet_remove_all">Удалить все</string>
|
||||||
<string name="downloaded_bottom_sheet_shuffle">Смешать</string>
|
<string name="downloaded_bottom_sheet_shuffle">Перемешать</string>
|
||||||
<string name="empty_string"></string>
|
<string name="empty_string"/>
|
||||||
<string name="error_required">Необходимый</string>
|
<string name="error_required">Обязательно</string>
|
||||||
<string name="error_server_prefix">Требуется префикс http или https</string>
|
<string name="error_server_prefix">Требуется префикс http или https</string>
|
||||||
<string name="exo_download_notification_channel_name">Загрузки</string>
|
<string name="exo_download_notification_channel_name">Загрузки</string>
|
||||||
|
<string name="exo_controls_heart_off_description">Убрать лайк</string>
|
||||||
|
<string name="exo_controls_heart_on_description">Поставить лайк</string>
|
||||||
|
<string name="cast_expanded_controller_loading">Загрузка…</string>
|
||||||
<string name="filter_info_selection">Выберите два или более фильтров</string>
|
<string name="filter_info_selection">Выберите два или более фильтров</string>
|
||||||
<string name="filter_title">Фильтр</string>
|
<string name="filter_title">Фильтр</string>
|
||||||
<string name="filter_artist">Фильтровать исполнителей</string>
|
<string name="filter_artist">Фильтровать исполнителей</string>
|
||||||
<string name="filter_title_expanded">Фильтровать жанры</string>
|
<string name="filter_title_expanded">Фильтровать по жанрам</string>
|
||||||
|
<string name="generic_list_page_count">(%1$d)</string>
|
||||||
|
<string name="generic_list_page_count_unknown">(+%1$d)</string>
|
||||||
<string name="genre_catalogue_title">Каталог жанров</string>
|
<string name="genre_catalogue_title">Каталог жанров</string>
|
||||||
<string name="genre_catalogue_title_expanded">Просмотр жанров</string>
|
<string name="genre_catalogue_title_expanded">Обзор жанров</string>
|
||||||
<string name="github_update_dialog_negative_button">Напомнить позже</string>
|
<string name="github_update_dialog_negative_button">Напомнить позже</string>
|
||||||
<string name="github_update_dialog_neutral_button">Поддержать меня</string>
|
<string name="github_update_dialog_neutral_button">Поддержать меня</string>
|
||||||
<string name="github_update_dialog_positive_button">Скачать сейчас</string>
|
<string name="github_update_dialog_positive_button">Скачать сейчас</string>
|
||||||
<string name="github_update_dialog_summary">На Github доступна новая версия приложения.</string>
|
<string name="github_update_dialog_summary">На Github доступна новая версия приложения.</string>
|
||||||
<string name="github_update_dialog_title">Доступно обновление</string>
|
<string name="github_update_dialog_title">Доступно обновление</string>
|
||||||
<string name="home_rearrangement_dialog_negative_button">Отмена</string>
|
<string name="home_rearrangement_dialog_negative_button">Отмена</string>
|
||||||
<string name="home_rearrangement_dialog_neutral_button">Перезагрузить</string>
|
<string name="home_rearrangement_dialog_neutral_button">Сброс</string>
|
||||||
<string name="home_rearrangement_dialog_positive_button">Сохранять</string>
|
<string name="home_rearrangement_dialog_positive_button">Сохранить</string>
|
||||||
<string name="home_rearrangement_dialog_title">Настроить главную</string>
|
<string name="home_rearrangement_dialog_title">Настроить главную</string>
|
||||||
<string name="home_rearrangement_dialog_subtitle">Обратите внимание, чтобы внесенные изменения вступили в силу, необходимо перезапустить приложение.</string>
|
<string name="home_rearrangement_dialog_subtitle">Чтобы внесенные изменения вступили в силу, необходимо перезапустить приложение.</string>
|
||||||
<string name="home_section_music">Музыка</string>
|
<string name="home_section_music">Музыка</string>
|
||||||
<string name="home_section_podcast">Подкасты</string>
|
<string name="home_section_podcast">Подкасты</string>
|
||||||
<string name="home_section_radio">Радио</string>
|
<string name="home_section_radio">Радио</string>
|
||||||
<string name="home_subtitle_best_of">Лучшие треки любимых исполнителей</string>
|
<string name="home_subtitle_best_of">Лучшие треки любимых исполнителей</string>
|
||||||
<string name="home_subtitle_made_for_you">Запустите микс с понравившимся вам треком</string>
|
<string name="home_subtitle_made_for_you">Начните микс с понравившегося трека</string>
|
||||||
<string name="home_subtitle_new_internet_radio_station">Добавить новое радио</string>
|
<string name="home_subtitle_new_internet_radio_station">Добавить новое радио</string>
|
||||||
<string name="home_subtitle_new_podcast_channel">Добавить новый канал подкаста</string>
|
<string name="home_subtitle_new_podcast_channel">Добавить новый канал подкаста</string>
|
||||||
<string name="home_sync_starred_cancel">Отмена</string>
|
<string name="home_sync_starred_cancel">Отмена</string>
|
||||||
<string name="home_sync_starred_download">Скачать</string>
|
<string name="home_sync_starred_download">Скачать</string>
|
||||||
<string name="home_sync_starred_subtitle">Загрузка этих треков может потребовать значительного использования данных</string>
|
<string name="home_sync_starred_subtitle">Загрузка этих треков может потребовать значительный объем трафика</string>
|
||||||
<string name="home_sync_starred_title">Похоже, есть несколько отмеченных треков для синхронизации.</string>
|
<string name="home_sync_starred_title">Похоже, есть любимые треки для синхронизации</string>
|
||||||
<string name="home_sync_starred_albums_title">Синхронизировать отмеченные альбомы</string>
|
<string name="home_sync_starred_albums_title">Синхронизиция любимых альбомов</string>
|
||||||
<string name="home_sync_starred_albums_subtitle">Отмеченные альбомы будут доступны в автономном режиме</string>
|
<string name="home_sync_starred_albums_subtitle">Любимые альбомы будут доступны офлайн</string>
|
||||||
|
<string name="home_sync_starred_artists_title">Синхронизиция любимых артистов</string>
|
||||||
|
<string name="home_sync_starred_artists_subtitle">У вас есть любимые артисты, музыка которых не скачана</string>
|
||||||
|
<plurals name="home_sync_starred_songs_count">
|
||||||
|
<item quantity="one">%d трек требует синхронизации</item>
|
||||||
|
<item quantity="other">%d треков требуют синхронизации</item>
|
||||||
|
</plurals>
|
||||||
<string name="home_title_best_of">Лучшее из</string>
|
<string name="home_title_best_of">Лучшее из</string>
|
||||||
<string name="home_title_discovery">Открытие</string>
|
<string name="home_title_discovery">Открытие</string>
|
||||||
<string name="home_title_discovery_shuffle_all_button">Перемешать все</string>
|
<string name="home_title_discovery_shuffle_all_button">Перемешать все</string>
|
||||||
<string name="home_title_flashback">Воспоминание</string>
|
<string name="home_title_flashback">Воспоминание</string>
|
||||||
<string name="home_title_internet_radio_station">Интернет-радиостанции</string>
|
<string name="home_title_internet_radio_station">Интернет-радиостанции</string>
|
||||||
<string name="home_title_last_played">Последнее воспроизведение</string>
|
<string name="home_title_last_played">Недавно воспроизведенные</string>
|
||||||
<string name="home_title_last_played_see_all_button">Увидеть все</string>
|
<string name="home_title_last_played_see_all_button">Все</string>
|
||||||
<string name="home_title_last_week">На прошлой неделе</string>
|
<string name="home_title_last_week">Прошлая неделя</string>
|
||||||
<string name="home_title_last_month">Прошлый месяц</string>
|
<string name="home_title_last_month">Прошлый месяц</string>
|
||||||
<string name="home_title_last_year">Прошлый год</string>
|
<string name="home_title_last_year">Прошлый год</string>
|
||||||
<string name="home_title_made_for_you">Сделано для тебя</string>
|
<string name="home_title_made_for_you">Персональная подборка</string>
|
||||||
<string name="home_title_most_played">Самое популярное</string>
|
<string name="home_title_most_played">Популярные</string>
|
||||||
<string name="home_title_most_played_see_all_button">Увидеть все</string>
|
<string name="home_title_most_played_see_all_button">Все</string>
|
||||||
<string name="home_title_new_releases">Новые релизы</string>
|
<string name="home_title_new_releases">Новые релизы</string>
|
||||||
<string name="home_title_newest_podcasts">Новейшие подкасты</string>
|
<string name="home_title_newest_podcasts">Новые подкасты</string>
|
||||||
<string name="home_title_pinned_playlists">Плейлисты</string>
|
<string name="home_title_pinned_playlists">Плейлисты</string>
|
||||||
<string name="home_title_podcast_channels">Каналы</string>
|
<string name="home_title_podcast_channels">Каналы</string>
|
||||||
<string name="home_title_podcast_channels_see_all_button">Увидеть все</string>
|
<string name="home_title_podcast_channels_see_all_button">Все</string>
|
||||||
<string name="home_title_radio_station">Радиостанции</string>
|
<string name="home_title_radio_station">Радиостанции</string>
|
||||||
<string name="home_title_recently_added">Недавно добавленный</string>
|
<string name="home_title_recently_added">Недавно добавленные</string>
|
||||||
<string name="home_title_recently_added_see_all_button">Увидеть все</string>
|
<string name="home_title_recently_added_see_all_button">Все</string>
|
||||||
<string name="home_title_shares">Общий доступ</string>
|
<string name="home_title_shares">Общий доступ</string>
|
||||||
<string name="home_title_starred_albums">★ Отмеченные альбомы</string>
|
<string name="home_title_starred_albums">★ Любимые альбомы</string>
|
||||||
<string name="home_title_starred_albums_see_all_button">Увидеть все</string>
|
<string name="home_title_starred_albums_see_all_button">Все</string>
|
||||||
<string name="home_title_starred_artists">★ Рейтинговые артисты</string>
|
<string name="home_title_starred_artists">★ Любимые исполнители</string>
|
||||||
<string name="home_title_starred_artists_see_all_button">Увидеть все</string>
|
<string name="home_title_starred_artists_see_all_button">Все</string>
|
||||||
<string name="home_title_starred_tracks">★ Отмеченные треки</string>
|
<string name="home_title_starred_tracks">★ Любимые треки</string>
|
||||||
<string name="home_title_starred_tracks_see_all_button">Увидеть все</string>
|
<string name="home_title_starred_tracks_see_all_button">Все</string>
|
||||||
<string name="home_title_top_songs">Ваши лучшие треки</string>
|
<string name="home_title_top_songs">Ваши лучшие треки</string>
|
||||||
<string name="home_option_reorganize">Реорганизовать</string>
|
<string name="home_option_reorganize">Настроить</string>
|
||||||
|
<string name="label_dot_separator" translatable="false">•</string>
|
||||||
|
<string name="label_placeholder" translatable="false">--</string>
|
||||||
<string name="library_title_album">Альбомы</string>
|
<string name="library_title_album">Альбомы</string>
|
||||||
<string name="library_title_album_see_all_button">Увидеть все</string>
|
<string name="library_title_album_see_all_button">Все</string>
|
||||||
<string name="library_title_artist">Исполнители</string>
|
<string name="library_title_artist">Исполнители</string>
|
||||||
<string name="library_title_artist_see_all_button">Увидеть все</string>
|
<string name="library_title_artist_see_all_button">Все</string>
|
||||||
<string name="library_title_genre">Жанры</string>
|
<string name="library_title_genre">Жанры</string>
|
||||||
<string name="library_title_genre_see_all_button">Увидеть все</string>
|
<string name="library_title_genre_see_all_button">Все</string>
|
||||||
<string name="library_title_music_folder">Музыкальные папки</string>
|
<string name="library_title_music_folder">Папки с музыкой</string>
|
||||||
<string name="library_title_playlist">Плейлисты</string>
|
<string name="library_title_playlist">Плейлисты</string>
|
||||||
<string name="library_title_playlist_see_all_button">Увидеть все</string>
|
<string name="library_title_playlist_see_all_button">Все</string>
|
||||||
<string name="login_empty">Сервер не добавлен</string>
|
<string name="login_empty">Сервер не добавлен</string>
|
||||||
<string name="login_title">Subsonic серверы</string>
|
<string name="login_title">Subsonic серверы</string>
|
||||||
<string name="login_title_expanded">Subsonic серверы</string>
|
<string name="login_title_expanded">Subsonic серверы</string>
|
||||||
@@ -164,7 +207,7 @@
|
|||||||
<string name="menu_add_to_playlist_button">Добавить в плейлист</string>
|
<string name="menu_add_to_playlist_button">Добавить в плейлист</string>
|
||||||
<string name="menu_download_all_button">Скачать все</string>
|
<string name="menu_download_all_button">Скачать все</string>
|
||||||
<string name="menu_rate_album">Оценить альбом</string>
|
<string name="menu_rate_album">Оценить альбом</string>
|
||||||
<string name="menu_download_label">Скачать</string>
|
<string name="menu_download_label">Скачанное</string>
|
||||||
<string name="menu_filter_all">Все</string>
|
<string name="menu_filter_all">Все</string>
|
||||||
<string name="menu_filter_download">Загружено</string>
|
<string name="menu_filter_download">Загружено</string>
|
||||||
<string name="menu_group_by_album">Альбом</string>
|
<string name="menu_group_by_album">Альбом</string>
|
||||||
@@ -180,58 +223,75 @@
|
|||||||
<string name="menu_search_button">Поиск</string>
|
<string name="menu_search_button">Поиск</string>
|
||||||
<string name="menu_settings_button">Настройки</string>
|
<string name="menu_settings_button">Настройки</string>
|
||||||
<string name="menu_sort_artist">Исполнитель</string>
|
<string name="menu_sort_artist">Исполнитель</string>
|
||||||
<string name="menu_sort_name">Имя</string>
|
<string name="menu_sort_name">Название</string>
|
||||||
<string name="menu_sort_random">Случайный</string>
|
<string name="menu_sort_random">Случайно</string>
|
||||||
<string name="menu_sort_recently_added">Недавно добавленный</string>
|
<string name="menu_sort_album_count">Количество альбомов</string>
|
||||||
<string name="menu_sort_recently_played">Недавно воспроизведенный</string>
|
<string name="menu_sort_recently_added">Недавно добавленные</string>
|
||||||
<string name="menu_sort_most_played">Самое популярное</string>
|
<string name="menu_sort_recently_played">Недавно воспроизведенные</string>
|
||||||
<string name="menu_sort_most_recently_starred">Недавно отмеченный</string>
|
<string name="menu_sort_most_played">Популярные</string>
|
||||||
<string name="menu_sort_least_recently_starred">Давно отмеченный</string>
|
<string name="menu_sort_most_recently_starred">Недавно понравившиеся</string>
|
||||||
|
<string name="menu_sort_least_recently_starred">Давно понравившиеся</string>
|
||||||
<string name="menu_sort_year">Год</string>
|
<string name="menu_sort_year">Год</string>
|
||||||
<string name="menu_pin_button">Добавить на главный экран</string>
|
<string name="menu_pin_button">Добавить на главный экран</string>
|
||||||
<string name="menu_unpin_button">Убрать с главного экрана</string>
|
<string name="menu_unpin_button">Убрать с главного экрана</string>
|
||||||
<string name="player_playback_speed">%1$.2fx</string>
|
<string name="player_playback_speed">%1$.2fx</string>
|
||||||
<string name="player_queue_clean_all_button">Очистить очередь воспроизведения</string>
|
<string name="playback_speed_dialog_title">Скорость воспроизведения</string>
|
||||||
|
<string name="playback_speed_dialog_negative_button">Отмена</string>
|
||||||
|
<string name="player_queue_clean_all_button">Очистить очередь</string>
|
||||||
<string name="player_queue_save_queue_success">Очередь сохранена</string>
|
<string name="player_queue_save_queue_success">Очередь сохранена</string>
|
||||||
|
<string name="player_queue_save_to_playlist">Сохранить очередь в плейлист</string>
|
||||||
|
<string name="player_queue_load_queue">Загрузить очередь</string>
|
||||||
|
<string name="player_lyrics_download_content_description">Скачать текст песни для офлайн-прослушивания</string>
|
||||||
|
<string name="player_lyrics_downloaded_content_description">Текст песни сохранён для офлайн-прослушивания</string>
|
||||||
|
<string name="player_lyrics_download_success">Текст песни сохранён для офлайн-прослушивания.</string>
|
||||||
|
<string name="player_lyrics_download_failure">Текст песни недоступен для скачивания.</string>
|
||||||
<string name="player_server_priority">Приоритет сервера</string>
|
<string name="player_server_priority">Приоритет сервера</string>
|
||||||
<string name="player_unknown_format">Неизвестный форма</string>
|
<string name="player_unknown_format">Неизвестный формат</string>
|
||||||
<string name="player_transcoding">Транскодирование</string>
|
<string name="player_transcoding">Транскодирвание</string>
|
||||||
<string name="player_transcoding_requested">запрошено</string>
|
<string name="player_transcoding_requested">запрошено</string>
|
||||||
<string name="playlist_catalogue_title">Каталог плейлистов</string>
|
<string name="playlist_catalogue_title">Каталог плейлистов</string>
|
||||||
<string name="playlist_catalogue_title_expanded">Просмотр плейлистов</string>
|
<string name="playlist_catalogue_title_expanded">Обзор плейлистов</string>
|
||||||
<string name="playlist_chooser_dialog_empty">Плейлисты не созданы</string>
|
<string name="playlist_chooser_dialog_empty">Плейлисты не созданы</string>
|
||||||
<string name="playlist_chooser_dialog_cancel_button">Отмена</string>
|
<string name="playlist_chooser_dialog_cancel_button">Отмена</string>
|
||||||
<string name="playlist_chooser_dialog_create_button">Создать</string>
|
<string name="playlist_chooser_dialog_create_button">Создать</string>
|
||||||
<string name="playlist_chooser_dialog_title">Добавить в плейлист</string>
|
<string name="playlist_chooser_dialog_title">Добавить в плейлист</string>
|
||||||
<string name="playlist_chooser_dialog_toast_add_success">Добавьте песню в плейлист</string>
|
<string name="playlist_chooser_dialog_toast_add_success">Трек(и) добавлены в плейлист</string>
|
||||||
<string name="playlist_chooser_dialog_toast_add_failure">Не удалось добавить песню в список воспроизведения</string>
|
<string name="playlist_chooser_dialog_toast_add_failure">Не удалось добавить трек(и) в плейлист</string>
|
||||||
|
<string name="playlist_chooser_dialog_toast_remove_success">Трек удалён из плейлиста</string>
|
||||||
|
<string name="playlist_chooser_dialog_toast_remove_failure">Не удалось удалить трек из плейлиста</string>
|
||||||
|
<string name="playlist_chooser_dialog_toast_all_skipped">Все треки пропущены как дубликаты</string>
|
||||||
|
<string name="playlist_chooser_dialog_visibility_public">Публичный</string>
|
||||||
|
<string name="playlist_chooser_dialog_visibility_private">Приватный</string>
|
||||||
|
<string name="playlist_chooser_dialog_visibility_switch_label">Сделать плейлист публичным</string>
|
||||||
|
<string name="playlist_chooser_dialog_visibility_summary">Сервер обновляет видимость при каждом запросе. По умолчанию плейлист приватный.</string>
|
||||||
<string name="playlist_counted_tracks">%1$d треков • %2$s</string>
|
<string name="playlist_counted_tracks">%1$d треков • %2$s</string>
|
||||||
<string name="playlist_duration">Продолжительность • %1$s</string>
|
<string name="playlist_duration">Длительность • %1$s</string>
|
||||||
<string name="playlist_editor_dialog_action_delete_toast">Долгое нажатие для удаления</string>
|
<string name="playlist_editor_dialog_action_delete_toast">Удерживайте для удаления</string>
|
||||||
<string name="playlist_editor_dialog_hint_name">Название плейлиста</string>
|
<string name="playlist_editor_dialog_hint_name">Название плейлиста</string>
|
||||||
<string name="playlist_editor_dialog_negative_button">Отмена</string>
|
<string name="playlist_editor_dialog_negative_button">Отмена</string>
|
||||||
<string name="playlist_editor_dialog_neutral_button">Удалить</string>
|
<string name="playlist_editor_dialog_neutral_button">Удалить</string>
|
||||||
<string name="playlist_editor_dialog_positive_button">Сохранять</string>
|
<string name="playlist_editor_dialog_positive_button">Сохранить</string>
|
||||||
<string name="playlist_editor_dialog_title">Редактировать плейлист</string>
|
<string name="playlist_editor_dialog_title">Редактировать плейлист</string>
|
||||||
<string name="playlist_page_play_button">Воспроизвести</string>
|
<string name="playlist_page_play_button">Воспроизвести</string>
|
||||||
<string name="playlist_page_shuffle_button">Смешать</string>
|
<string name="playlist_page_shuffle_button">Перемешать</string>
|
||||||
<string name="playlist_song_count">Плейлист • %1$d треки</string>
|
<string name="playlist_song_count">Плейлист • %1$d треков</string>
|
||||||
<string name="podcast_bottom_sheet_add_to_queue">Добавить в очередь</string>
|
<string name="podcast_bottom_sheet_add_to_queue">Добавить в очередь</string>
|
||||||
<string name="podcast_bottom_sheet_delete">Удалить</string>
|
<string name="podcast_bottom_sheet_delete">Удалить</string>
|
||||||
<string name="podcast_bottom_sheet_download">Скачать</string>
|
<string name="podcast_bottom_sheet_download">Скачать</string>
|
||||||
<string name="podcast_bottom_sheet_go_to_channel">Перейти на канал</string>
|
<string name="podcast_bottom_sheet_go_to_channel">Перейти к каналу</string>
|
||||||
<string name="podcast_bottom_sheet_play_next">Играть дальше</string>
|
<string name="podcast_bottom_sheet_play_next">Играть следующим</string>
|
||||||
<string name="podcast_bottom_sheet_remove">Удалить</string>
|
<string name="podcast_bottom_sheet_remove">Удалить</string>
|
||||||
<string name="podcast_channel_catalogue_title">Каналы</string>
|
<string name="podcast_channel_catalogue_title">Каналы</string>
|
||||||
<string name="podcast_channel_catalogue_title_expanded">Просмотр каналов</string>
|
<string name="podcast_channel_catalogue_title_expanded">Обзор каналов</string>
|
||||||
<string name="podcast_channel_editor_dialog_hint_rss_url">RSS-адрес</string>
|
<string name="podcast_channel_editor_dialog_hint_rss_url">RSS-адрес</string>
|
||||||
<string name="podcast_channel_editor_dialog_title">Подкаст-канал</string>
|
<string name="podcast_channel_editor_dialog_title">Канал подкаста</string>
|
||||||
|
<string name="podcast_channel_not_supported_snackbar">Подкасты не поддерживаются этим сервером.</string>
|
||||||
<string name="podcast_channel_page_title_description_section">Описание</string>
|
<string name="podcast_channel_page_title_description_section">Описание</string>
|
||||||
<string name="podcast_channel_page_title_episode_section">Эпизоды</string>
|
<string name="podcast_channel_page_title_episode_section">Эпизоды</string>
|
||||||
<string name="podcast_channel_page_title_no_episode_available">Нет доступных серий</string>
|
<string name="podcast_channel_page_title_no_episode_available">Эпизоды отсутствуют</string>
|
||||||
<string name="podcast_episode_download_request_snackbar">Ваш запрос отправлен на сервер</string>
|
<string name="podcast_episode_download_request_snackbar">Ваш запрос отправлен на сервер</string>
|
||||||
<string name="podcast_info_empty_button">Нажмите, чтобы скрыть раздел. Изменения будут видны при перезапуске</string>
|
<string name="podcast_info_empty_button">Нажмите, чтобы скрыть раздел\nИзменения вступят в силу после перезапуска</string>
|
||||||
<string name="podcast_info_empty_subtitle">Добавив канал, вы найдете его здесь</string>
|
<string name="podcast_info_empty_subtitle">После добавления канала он появится здесь</string>
|
||||||
<string name="podcast_info_empty_title">Подкасты не найдены!</string>
|
<string name="podcast_info_empty_title">Подкасты не найдены!</string>
|
||||||
<string name="podcast_release_date_duration_formatter">%1$s • %2$s</string>
|
<string name="podcast_release_date_duration_formatter">%1$s • %2$s</string>
|
||||||
<string name="radio_editor_dialog_hint_homepage_url">URL-адрес домашней страницы радио</string>
|
<string name="radio_editor_dialog_hint_homepage_url">URL-адрес домашней страницы радио</string>
|
||||||
@@ -239,215 +299,310 @@
|
|||||||
<string name="radio_editor_dialog_hint_stream_url">URL-адрес радиопотока</string>
|
<string name="radio_editor_dialog_hint_stream_url">URL-адрес радиопотока</string>
|
||||||
<string name="radio_editor_dialog_negative_button">Отмена</string>
|
<string name="radio_editor_dialog_negative_button">Отмена</string>
|
||||||
<string name="radio_editor_dialog_neutral_button">Удалить</string>
|
<string name="radio_editor_dialog_neutral_button">Удалить</string>
|
||||||
<string name="radio_editor_dialog_positive_button">Сохранять</string>
|
<string name="radio_editor_dialog_positive_button">Сохранить</string>
|
||||||
|
<string name="radio_editor_dialog_added">Радиостанция добавлена</string>
|
||||||
|
<string name="radio_editor_dialog_updated">Радиостанция обновлена</string>
|
||||||
<string name="radio_editor_dialog_title">Интернет-радиостанция</string>
|
<string name="radio_editor_dialog_title">Интернет-радиостанция</string>
|
||||||
<string name="radio_station_info_empty_button">Нажмите, чтобы скрыть раздел. Изменения будут видны при перезапуске</string>
|
<string name="radio_station_info_empty_button">Нажмите, чтобы скрыть раздел\nИзменения вступят в силу после перезапуска</string>
|
||||||
<string name="radio_station_info_empty_subtitle">Добавив радиостанцию, вы найдете ее здесь</string>
|
<string name="radio_station_info_empty_subtitle">После добавления радиостанции она появится здесь</string>
|
||||||
<string name="radio_station_info_empty_title">Станции не найдены!</string>
|
<string name="radio_station_info_empty_title">Станции не найдены!</string>
|
||||||
|
<string name="radio_dialog_not_supported_snackbar">Управление интернет-радио не поддерживается этим сервером.</string>
|
||||||
<string name="rating_dialog_negative_button">Отмена</string>
|
<string name="rating_dialog_negative_button">Отмена</string>
|
||||||
<string name="rating_dialog_positive_button">Сохранять</string>
|
<string name="rating_dialog_positive_button">Сохранить</string>
|
||||||
<string name="rating_dialog_title">Рейтинг</string>
|
<string name="rating_dialog_title">Рейтинг</string>
|
||||||
<string name="search_hint">Поиск по названию, исполнителям или альбомам</string>
|
<string name="search_hint">Поиск по названию, артистам или альбомам</string>
|
||||||
<string name="search_info_minimum_characters">Введите не менее трех символов</string>
|
<string name="search_info_minimum_characters">Введите не менее трех символов</string>
|
||||||
<string name="search_title_album">Альбомы</string>
|
<string name="search_title_album">Альбомы</string>
|
||||||
<string name="search_title_artist">Исполнители</string>
|
<string name="search_title_artist">Исполнители</string>
|
||||||
<string name="search_title_song">Треки</string>
|
<string name="search_title_song">Треки</string>
|
||||||
<string name="server_signup_dialog_action_low_security">Низкая безопасность</string>
|
<string name="server_signup_dialog_action_low_security">Низкая безопасность</string>
|
||||||
<string name="server_signup_dialog_action_delete_toast">Долгое нажатие для удаления</string>
|
<string name="server_signup_dialog_action_delete_toast">Удерживайте для удаления</string>
|
||||||
<string name="server_signup_dialog_hint_local_address">Локальный URL</string>
|
<string name="server_signup_dialog_hint_local_address">Локальный URL</string>
|
||||||
<string name="server_signup_dialog_hint_name">Имя сервера</string>
|
<string name="server_signup_dialog_hint_name">Название сервера</string>
|
||||||
<string name="server_signup_dialog_hint_password">Пароль</string>
|
<string name="server_signup_dialog_hint_password">Пароль</string>
|
||||||
<string name="server_signup_dialog_hint_url">URL-адрес сервера</string>
|
<string name="server_signup_dialog_hint_url">URL-адрес сервера</string>
|
||||||
<string name="server_signup_dialog_hint_username">Имя пользователя</string>
|
<string name="server_signup_dialog_hint_username">Имя пользователя</string>
|
||||||
|
<string name="server_signup_dialog_hint_client_certificate">Клиентский сертификат (необязательно)</string>
|
||||||
<string name="server_signup_dialog_negative_button">Отмена</string>
|
<string name="server_signup_dialog_negative_button">Отмена</string>
|
||||||
<string name="server_signup_dialog_neutral_button">Удалить</string>
|
<string name="server_signup_dialog_neutral_button">Удалить</string>
|
||||||
<string name="server_signup_dialog_positive_button">Сохранить</string>
|
<string name="server_signup_dialog_positive_button">Сохранить</string>
|
||||||
<string name="server_signup_dialog_title">Добавить сервер</string>
|
<string name="server_signup_dialog_title">Добавить сервер</string>
|
||||||
<string name="server_unreachable_dialog_negative_button">Отмена</string>
|
<string name="server_unreachable_dialog_negative_button">Отмена</string>
|
||||||
<string name="server_unreachable_dialog_neutral_button">Перейти к входу</string>
|
<string name="server_unreachable_dialog_neutral_button">Перейти ко входу</string>
|
||||||
<string name="server_unreachable_dialog_positive_button">Продолжить в любом случае</string>
|
<string name="server_unreachable_dialog_positive_button">Продолжить в любом случае</string>
|
||||||
<string name="server_unreachable_dialog_summary">Запрошенный сервер недоступен. Если вы решите продолжить, это диалоговое окно не появится в течение следующего часа</string>
|
<string name="server_unreachable_dialog_summary">Запрошенный сервер недоступен. Если вы продолжите, это сообщение не появится в течение следующего часа.</string>
|
||||||
<string name="server_unreachable_dialog_title">Сервер недоступен</string>
|
<string name="server_unreachable_dialog_title">Сервер недоступен</string>
|
||||||
<string name="settings_about_summary">Tempus — это легкий музыкальный клиент с открытым исходным кодом для Subsonic, разработанный и созданный специально для Android.</string>
|
<string name="settings_about_summary">Tempus — это легкий музыкальный клиент с открытым исходным кодом для Subsonic, разработанный специально под Android.</string>
|
||||||
<string name="settings_about_title">О нас</string>
|
<string name="settings_about_title">О приложении</string>
|
||||||
<string name="settings_album_detail">Показать детали альбома</string>
|
<string name="settings_always_on_display">Always On Display</string>
|
||||||
<string name="settings_album_detail_summary">Если включено, отображать информацию об альбоме, например жанр, количество песен и т. д., на странице альбома.</string>
|
<string name="settings_allow_playlist_duplicates">Разрешить дубликаты в плейлистах</string>
|
||||||
<string name="settings_allow_playlist_duplicates">Разрешить добавление дубликатов в плейлист</string>
|
<string name="settings_allow_playlist_duplicates_summary">Если включено, дубликаты не будут проверяться при добавлении в плейлист.</string>
|
||||||
<string name="settings_allow_playlist_duplicates_summary">Если включено, дубликаты не будут проверяться при добавлении в плейлист..</string>
|
<string name="settings_audio_transcode_download_format">Формат транскодирования</string>
|
||||||
<string name="settings_always_on_display">Всегда на дисплее</string>
|
<string name="settings_audio_transcode_download_priority_summary">Если включено, Tempus не будет принудительно скачивать трек с настройками транскодирования, указанными ниже.</string>
|
||||||
<string name="settings_artist_sort_by_album_count">Сортировать исполнителей по количеству альбомов</string>
|
<string name="settings_audio_transcode_download_priority_title">Использовать серверные настройки транскодирования при скачивании</string>
|
||||||
<string name="settings_artist_sort_by_album_count_summary">Если включено, сортировать исполнителей по количеству альбомов. Если отключено, сортировать по имени.</string>
|
<string name="settings_audio_transcode_download_summary">Если включено, Tempus будет скачивать треки в транскодированном виде.</string>
|
||||||
<string name="settings_audio_transcode_download_format">Формат перекодирования</string>
|
<string name="settings_audio_transcode_download_title">Скачивать транскодированные треки</string>
|
||||||
<string name="settings_audio_transcode_download_priority_summary">Если этот параметр включен, Tempus не будет принудительно загружать трек с настройками перекодирования, указанными ниже.</string>
|
<string name="settings_audio_transcode_estimate_content_length_summary">Если включено, на сервере будет запрошена предполагаемая продолжительность трека.</string>
|
||||||
<string name="settings_audio_transcode_download_priority_title">Установите приоритет настроек сервера, используемых для потоковой передачи при загрузке</string>
|
<string name="settings_audio_transcode_estimate_content_length_title">Оценить длительность трека</string>
|
||||||
<string name="settings_audio_transcode_download_summary">Если этот параметр включен, Tempus будет загружать перекодированные треки.</string>
|
<string name="settings_audio_transcode_format_download">Формат при скачивании</string>
|
||||||
<string name="settings_audio_transcode_download_title">Скачать перекодированные треки</string>
|
<string name="settings_audio_transcode_format_mobile">Формат транскод. в моб. сети 4G/5G</string>
|
||||||
<string name="settings_audio_transcode_estimate_content_length_summary">Если этот параметр включен, на сервере будет запрошена предполагаемая продолжительность трека.</string>
|
<string name="settings_audio_transcode_format_wifi">Формат транскод. в сети Wi-Fi</string>
|
||||||
<string name="settings_audio_transcode_estimate_content_length_title">Оцените длину содержимого</string>
|
<string name="settings_audio_transcode_priority_summary">Если включено, Tempus не будет принудительно стримить трек с настройками транскодирования, указанными ниже.</string>
|
||||||
<string name="settings_audio_transcode_format_download">Формат перекодирования для загрузки</string>
|
<string name="settings_audio_transcode_priority_title">Приоритет серверных настроек транскодирования</string>
|
||||||
<string name="settings_audio_transcode_format_mobile">Формат перекодирования в мобильном телефоне</string>
|
<string name="settings_audio_transcode_priority_toast">Приоритет транскодирования передан серверу</string>
|
||||||
<string name="settings_audio_transcode_format_wifi">Перекодировать формат в Wi-Fi</string>
|
|
||||||
<string name="settings_audio_transcode_priority_summary">Если этот параметр включен, Tempus не будет принудительно транслировать трек с настройками перекодирования, указанными ниже.</string>
|
|
||||||
<string name="settings_audio_transcode_priority_title">Приоритизация настроек перекодирования сервера</string>
|
|
||||||
<string name="settings_audio_transcode_priority_toast">Приоритет при перекодировании трека отдается серверу</string>
|
|
||||||
<string name="settings_buffering_strategy">Стратегия буферизации</string>
|
<string name="settings_buffering_strategy">Стратегия буферизации</string>
|
||||||
<string name="settings_buffering_strategy_summary">Чтобы изменения вступили в силу, необходимо вручную перезапустить приложение.</string>
|
<string name="settings_buffering_strategy_summary">Чтобы изменения вступили в силу, необходимо перезапустить приложение.</string>
|
||||||
<string name="settings_continuous_play_summary">Разрешить играть включать треки после окончания плейлиста</string>
|
<string name="settings_choose_download_folder">Выберите папку для загруженной музыки</string>
|
||||||
<string name="settings_continuous_play_title">Продолжать играть</string>
|
<string name="settings_clear_download_folder">Сбросить папку загрузок</string>
|
||||||
<string name="settings_covers_cache">Размер кэша обложек</string>
|
<string name="settings_continuous_play_summary">Позволяет продолжать воспроизведение после окончания плейлиста</string>
|
||||||
<string name="settings_data_saving_mode_summary">Чтобы сократить потребление данных, избегайте загрузки обложек.</string>
|
<string name="settings_continuous_play_title">Непрерывное воспроизведение</string>
|
||||||
<string name="settings_data_saving_mode_title">Ограничить использование мобильных данных</string>
|
<string name="settings_covers_cache">Кэш обложек</string>
|
||||||
<string name="settings_delete_download_storage_summary">Продолжение приведет к необратимому удалению всех сохраненных элементов.</string>
|
<string name="settings_data_saving_mode_summary">Чтобы снизить расход трафика, обложки не будут загружаться.</string>
|
||||||
<string name="settings_delete_download_storage_title">Удалить сохраненные элементы</string>
|
<string name="settings_data_saving_mode_title">Экономия мобильного трафика</string>
|
||||||
<string name="settings_download_storage_title">Загрузить хранилище</string>
|
<string name="settings_delete_download_storage_summary">Продолжение приведёт к безвозвратному удалению всех сохранённых элементов.</string>
|
||||||
<string name="settings_system_equalizer_summary">Отрегулируйте настройки звука</string>
|
<string name="settings_delete_download_storage_title">Удалить сохранённые элементы</string>
|
||||||
|
<string name="settings_download_storage_title">Место хранения загрузок</string>
|
||||||
|
<string name="settings_download_folder_cleared">Папка для загрузок сброшена</string>
|
||||||
|
<string name="settings_download_folder_set">Папка для загрузок установлена</string>
|
||||||
|
<string name="settings_set_download_folder">Выбрать папку для загрузок</string>
|
||||||
|
<string name="settings_system_equalizer_summary">Настройки звука</string>
|
||||||
<string name="settings_system_equalizer_title">Системный эквалайзер</string>
|
<string name="settings_system_equalizer_title">Системный эквалайзер</string>
|
||||||
<string name="settings_github_link">https://github.com/eddyizm/tempus</string>
|
<string name="settings_github_link">https://github.com/eddyizm/tempus</string>
|
||||||
<string name="settings_github_summary">Следите за развитием</string>
|
<string name="settings_github_summary">Следите за развитием</string>
|
||||||
<string name="settings_github_title">Github</string>
|
<string name="settings_github_title">Github</string>
|
||||||
<string name="settings_image_size">Установить разрешение изображения</string>
|
<string name="settings_support_discussion_link" translatable="false">https://github.com/eddyizm/tempus/discussions</string>
|
||||||
|
<string name="settings_github_update">Обновления</string>
|
||||||
|
<string name="settings_github_update_title">Проверять обновления на GitHub</string>
|
||||||
|
<string name="settings_github_update_summary">Если используется версия из GitHub, приложение по умолчанию проверяет наличие новых APK-релизов. Отключите, чтобы запретить автоматическую проверку</string>
|
||||||
|
<string name="settings_support_summary">Присоединяйтесь к обсуждениям в сообществе и оказывайте поддержку</string>
|
||||||
|
<string name="settings_support_title">Поддержка пользователей</string>
|
||||||
|
<string name="settings_scan_result">Сканирование: найдено %1$d треков</string>
|
||||||
|
<string name="settings_image_size">Разрешение изображений</string>
|
||||||
<string name="settings_language">Язык</string>
|
<string name="settings_language">Язык</string>
|
||||||
<string name="settings_logout_title">Выйти</string>
|
<string name="settings_logout_title">Выйти</string>
|
||||||
<string name="settings_max_bitrate_download">Битрейт для скачиваний</string>
|
<string name="settings_ping_timeout_title">Тайм-аут подключения к серверу</string>
|
||||||
|
<string name="settings_ping_timeout_summary">Установите тайм-аут для локального URL. По умолчанию 2 секунды. (Для удалённого сервера значение x3, максимум 10 секунд.)</string>
|
||||||
|
<string name="settings_ping_timeout_dialog">Установите базовый тайм-аут в секундах</string>
|
||||||
|
<string name="settings_max_bitrate_download">Битрейт при скачивании</string>
|
||||||
<string name="settings_max_bitrate_mobile">Битрейт в мобильной сети 4G/5G</string>
|
<string name="settings_max_bitrate_mobile">Битрейт в мобильной сети 4G/5G</string>
|
||||||
<string name="settings_max_bitrate_wifi">Битрейт через соединение Wi-Fi</string>
|
<string name="settings_max_bitrate_wifi">Битрейт в сети Wi-Fi</string>
|
||||||
<string name="settings_media_cache">Размер кэша медиафайлов</string>
|
<string name="settings_media_cache">Размер кэша медиафайлов</string>
|
||||||
<string name="settings_music_directory">Показать музыкальные каталоги</string>
|
<string name="settings_music_directory">Показывать музыкальные каталоги</string>
|
||||||
<string name="settings_music_directory_summary">Если включено, то показывать раздел музыкального каталога. Обратите внимание: для правильной работы навигации по папкам сервер должен поддерживать эту функцию.</string>
|
<string name="settings_music_directory_summary">Если включено, отображается раздел музыкальных каталогов. Для корректной навигации сервер должен поддерживать эту функцию.</string>
|
||||||
<string name="settings_podcast">Показать подкаст</string>
|
<string name="settings_podcast">Показывать подкасты</string>
|
||||||
<string name="settings_podcast_summary">Если включено, показывать раздел подкаста. Перезапустите приложение, чтобы оно вступило в силу.</string>
|
<string name="settings_podcast_summary">Если включено, отображается раздел подкастов. Перезапустите приложение, чтобы изменение вступило в силу.</string>
|
||||||
<string name="settings_audio_quality">Показать качество звука (битрейт)</string>
|
<string name="settings_playlist_sort">Сортировка плейлистов</string>
|
||||||
<string name="settings_audio_quality_summary">Битрейт и аудиоформат будут показаны для каждой аудиодорожки.</string>
|
<string name="settings_androidauto">Android Auto</string>
|
||||||
<string name="settings_song_rating">Показать рейтинг трека</string>
|
<string name="settings_androidauto_album_view">Grid view for albums</string>
|
||||||
<string name="settings_song_rating_summary">Если эта функция включена, будет отображаться пятизвездочный рейтинг трека на странице воспроизведения\n\n*Требует перезапуска приложения</string>
|
<string name="settings_androidauto_home_view">Grid view for home</string>
|
||||||
<string name="settings_item_rating">Показать рейтинг</string>
|
<string name="settings_androidauto_playlist_view">Grid view for playlists</string>
|
||||||
<string name="settings_item_rating_summary">Если эта функция включена, будет отображаться рейтинг элемента и то, отмечен ли он как избранный.</string>
|
<string name="settings_androidauto_podcast_view">Grid view for podcast</string>
|
||||||
|
<string name="settings_androidauto_radio_view">Grid view for radio</string>
|
||||||
|
<string name="settings_androidauto_first_tab">First tab display</string>
|
||||||
|
<string name="settings_androidauto_second_tab">Second tab display</string>
|
||||||
|
<string name="settings_androidauto_third_tab">Third tab display</string>
|
||||||
|
<string name="settings_androidauto_fourth_tab">Fourth tab display</string>
|
||||||
|
<string name="settings_androidauto_shuffle_genre_songs">Перемешивать треки по жанру</string>
|
||||||
|
<string name="settings_androidauto_shuffle_genre_songs_summary">Воспроизводить случайные треки при выборе жанра</string>
|
||||||
|
<string name="settings_audio_quality">Показывать качество аудио</string>
|
||||||
|
<string name="settings_audio_quality_summary">Битрейт и формат аудио будут отображаться для каждого трека.</string>
|
||||||
|
<string name="settings_song_rating">Показывать рейтинг трека</string>
|
||||||
|
<string name="settings_song_rating_summary">Если включено, на странице воспроизведения будет отображаться пятизвёздочный рейтинг трека.\n\n*Требуется перезапуск приложения</string>
|
||||||
|
<string name="settings_item_rating">Показывать рейтинг элементов</string>
|
||||||
|
<string name="settings_item_rating_summary">Если включено, отображается рейтинг элемента и отметка избранного.</string>
|
||||||
<string name="settings_queue_syncing_countdown">Таймер синхронизации</string>
|
<string name="settings_queue_syncing_countdown">Таймер синхронизации</string>
|
||||||
<string name="settings_queue_syncing_summary">Если этот параметр включен, пользователь будет иметь возможность сохранять свою очередь воспроизведения и загружать состояние при открытии приложения.</string>
|
<string name="settings_queue_syncing_summary">Если включено, позволяет сохранять очередь воспроизведения и восстанавливать её при запуске приложения.</string>
|
||||||
<string name="settings_queue_syncing_title">Синхронизировать очередь воспроизведения для этого пользователя</string>
|
<string name="settings_queue_syncing_title">Синхронизация очереди воспроизведения [Экспериментально]</string>
|
||||||
<string name="settings_show_mini_shuffle_button">Показать кнопку Shuffle</string>
|
<string name="settings_show_mini_shuffle_button">Показывать кнопку перемешивания</string>
|
||||||
<string name="settings_show_mini_shuffle_button_summary">Если включено, показывать кнопку перемешивания, убрать сердечко в мини-плеере</string>
|
<string name="settings_show_mini_shuffle_button_summary">Если включено, в мини-плеере отображается кнопка перемешивания вместо сердечка.</string>
|
||||||
<string name="settings_radio">Показать радио</string>
|
<string name="settings_radio">Показывать радио</string>
|
||||||
<string name="settings_radio_summary">Если включено, показывать раздел радио. Перезапустите приложение, чтобы оно вступило в силу.</string>
|
<string name="settings_radio_summary">Если включено, отображается раздел радио. Перезапустите приложение, чтобы изменение вступило в силу.</string>
|
||||||
<string name="settings_auto_download_lyrics">Автоматическая загрузка текстов песен</string>
|
<string name="settings_enable_drawer_on_landscape">Включить боковое меню в портретном режиме [Экспериментально]</string>
|
||||||
<string name="settings_auto_download_lyrics_summary">Автоматически сохранять тексты песен, когда они доступны, чтобы их можно было просматривать в автономном режиме.</string>
|
<string name="settings_enable_drawer_on_landscape_summary">Разблокирует боковое меню в портретной ориентации. Изменения вступят в силу после перезапуска.</string>
|
||||||
<string name="settings_replay_gain">Установите режим усиления воспроизведения</string>
|
<string name="settings_hide_bottom_navbar_on_portrait">Скрывать нижнюю панель в портретном режиме [Экспериментально]</string>
|
||||||
<string name="settings_rounded_corner">Закругленные углы</string>
|
<string name="settings_hide_bottom_navbar_on_portrait_summary">Увеличивает вертикальное пространство, убирая нижнюю панель. Изменения вступят в силу после перезапуска.</string>
|
||||||
<string name="settings_rounded_corner_size">Размер углов</string>
|
<string name="settings_auto_download_lyrics">Автоматически скачивать тексты песен</string>
|
||||||
<string name="settings_rounded_corner_size_summary">Устанавливает величину угла кривизны.</string>
|
<string name="settings_auto_download_lyrics_summary">Тексты будут автоматически сохраняться, чтобы их можно было просматривать офлайн.</string>
|
||||||
<string name="settings_rounded_corner_summary">Если этот параметр включен, задает угол кривизны для всех отображаемых обложек. Изменения вступят в силу при перезапуске.</string>
|
<string name="settings_replay_gain">Режим ReplayGain</string>
|
||||||
|
<string name="settings_rounded_corner">Скругление углов</string>
|
||||||
|
<string name="settings_rounded_corner_size">Степень скругления углов</string>
|
||||||
|
<string name="settings_rounded_corner_size_summary">Определяет степень скругления углов.</string>
|
||||||
|
<string name="settings_rounded_corner_summary">Если включено, обложки будут отображаться со скругленными углами. Изменения вступят в силу после перезапуска.</string>
|
||||||
<string name="settings_scan_title">Сканировать библиотеку</string>
|
<string name="settings_scan_title">Сканировать библиотеку</string>
|
||||||
<string name="settings_scrobble_title">Включить скробблинг музыки Last.FM и т.д.</string>
|
<string name="settings_scrobble_title">Включить скробблинг музыки Last.FM и т.д.</string>
|
||||||
<string name="settings_system_language">Язык системы</string>
|
<string name="settings_system_language">Язык системы</string>
|
||||||
<string name="settings_share_title">Включить обмен музыкой</string>
|
<string name="settings_share_title">Включить обмен музыкой</string>
|
||||||
<string name="settings_streaming_cache_size">Размер кэша стриминга</string>
|
<string name="settings_streaming_cache_size">Кэш стриминга</string>
|
||||||
<string name="settings_streaming_cache_storage_title">Хранилище кэша стриминга</string>
|
<string name="settings_streaming_cache_storage_title">Хранилище кэша стриминга</string>
|
||||||
<string name="settings_sub_summary_scrobble">Важно отметить, что скробблинг также зависит от того, настроен ли сервер для получения этих данных.</string>
|
<string name="settings_sub_summary_scrobble">Важно отметить, что скробблинг зависит от того, настроен ли сервер для получения этих данных.</string>
|
||||||
<string name="settings_summary_skip_min_star_rating">При прослушивании радио исполнителя, мгновенном миксе или перемешивании всех, треки ниже определенного пользовательского рейтинга будут игнорироваться.</string>
|
<string name="settings_summary_skip_min_star_rating">При прослушивании радио исполнителя, мгновенного микса или при перемешивании все треки с рейтингом ниже указанного будут пропускаться.</string>
|
||||||
<string name="settings_summary_replay_gain">Усиление воспроизведения — это функция, которая позволяет регулировать уровень громкости звуковых дорожек для обеспечения единообразного качества прослушивания. Этот параметр действует только в том случае, если трек содержит необходимые метаданные.</string>
|
<string name="settings_summary_replay_gain">ReplayGain позволяет выровнять громкость аудиотреков для более комфортного прослушивания. Работает только если файл содержит соответствующие метаданные.</string>
|
||||||
<string name="settings_summary_scrobble">Скробблинг — это функция, которая позволяет вашему устройству отправлять информацию о песнях, которые вы слушаете, на музыкальный сервер. Эта информация помогает создавать персональные рекомендации на основе ваших музыкальных предпочтений.</string>
|
<string name="settings_summary_scrobble">Скробблинг позволяет отправлять информацию о прослушанных треках на музыкальный сервер. Это помогает формировать персональные рекомендации на основе ваших музыкальных предпочтений.</string>
|
||||||
<string name="settings_summary_share">Позволяет пользователю делиться музыкой по ссылке. Функциональность должна поддерживаться и включаться на стороне сервера и ограничивается отдельными треками, альбомами и плейлистами.</string>
|
<string name="settings_summary_share">Позволяет делиться музыкой по ссылке. Функция должна поддерживаться и включаться на стороне сервера и ограничивается отдельными треками, альбомами и плейлистами.</string>
|
||||||
<string name="settings_summary_syncing">Возвращает состояние очереди воспроизведения для этого пользователя. Сюда входят треки в очереди воспроизведения, воспроизводимый в данный момент трек и позиция внутри этого трека. Сервер должен поддерживать эту функцию.</string>
|
<string name="settings_summary_syncing">Возвращает состояние очереди воспроизведения пользователя: список треков, текущий трек и позицию воспроизведения. Сервер должен поддерживать эту функцию.\n*Работает не на всех серверах и устройствах.</string>
|
||||||
<string name="settings_summary_streaming_cache_size">%1$s \nСейчас используется: %2$s MiB</string>
|
<string name="settings_summary_streaming_cache_size">%1$s \nСейчас используется: %2$s MiB</string>
|
||||||
<string name="settings_summary_transcoding">Приоритет отдается режиму перекодирования. Если установлено «Прямое воспроизведение», битрейт файла не изменится.</string>
|
<string name="settings_summary_transcoding">Определяет приоритет режима транскодирования. Если выбрано «Прямое воспроизведение», битрейт файла не изменяется.</string>
|
||||||
<string name="settings_summary_transcoding_download">Загрузите перекодированные медиафайлы. Если этот параметр включен, будет использоваться не конечная точка загрузки, а следующие настройки. Если для параметра «Формат перекодирования для загрузки» установлено значение «Прямая загрузка», битрейт файла не изменится.</string>
|
<string name="settings_summary_transcoding_download">Загружать транскодированные медиафайлы. Если включено, для скачивания треков будут использоваться настройки ниже.\n\nЕсли для «Формат при скачивании» выбрано «Загружать оригинал», битрейт файла не изменяется.</string>
|
||||||
<string name="settings_summary_transcoding_estimate_content_length">Когда файл перекодируется на лету, клиент обычно не показывает длину трека. Можно запросить у серверов, поддерживающих данную функцию, оценку длительности воспроизводимого трека, но время ответа может занять больше времени.</string>
|
<string name="settings_summary_transcoding_estimate_content_length">При транскодировании на лету клиент может не отображать длительность трека. Есть возможность запросить у серверов, поддерживающих данную функцию, приблизительную длительность, но ответ может занять больше времени.</string>
|
||||||
<string name="settings_sync_starred_albums_for_offline_use_summary">Если этот параметр включен, помеченные альбомы будут загружены для использования в автономном режиме.</string>
|
<string name="settings_summary_landscape_items_per_row">Применяется ко всем спискам альбомов и исполнителей. По умолчанию: 4</string>
|
||||||
<string name="settings_sync_starred_albums_for_offline_use_title">Синхронизировать помеченные альбомы для использования в автономном режиме.</string>
|
<string name="settings_sync_starred_artists_for_offline_use_summary">Если включено, любимые исполнители будут скачиваться для офлайн-прослушивания.</string>
|
||||||
<string name="settings_sync_starred_tracks_for_offline_use_summary">Если этот параметр включен, помеченные треки будут загружены для использования в автономном режиме.</string>
|
<string name="settings_sync_starred_artists_for_offline_use_title">Синхронизировать избранных артистов для офлайн-прослушивания</string>
|
||||||
<string name="settings_sync_starred_tracks_for_offline_use_title">Синхронизировать помеченные треки для использования в автономном режиме.</string>
|
<string name="settings_sync_starred_albums_for_offline_use_summary">Если включено, любимые альбомы будут скачиваться для офлайн-прослушивания.</string>
|
||||||
<string name="settings_sync_starred_artists_for_offline_use_title">Синхронизировать избранных исполнителей для использования офлайн</string>
|
<string name="settings_sync_starred_albums_for_offline_use_title">Синхронизировать избранные альбомы для офлайн-прослушивания</string>
|
||||||
<string name="settings_support_summary">Присоединяйтесь к обсуждениям в сообществе и оказывайте поддержку</string>
|
<string name="settings_sync_starred_tracks_for_offline_use_summary">Если включено, любимые треки будут скачиваться для офлайн-прослушивания.</string>
|
||||||
<string name="settings_support_title">Поддержка пользователей</string>
|
<string name="settings_sync_starred_tracks_for_offline_use_title">Синхронизировать избранные треки для офлайн-прослушивания</string>
|
||||||
<string name="settings_theme">Тема</string>
|
<string name="settings_theme">Тема</string>
|
||||||
<string name="settings_title_data">Данные</string>
|
<string name="settings_title_data">Данные</string>
|
||||||
<string name="settings_title_general">Общий</string>
|
<string name="settings_title_general">Общие</string>
|
||||||
|
<string name="settings_title_playlist">Плейлисты</string>
|
||||||
<string name="settings_title_rating">Рейтинг</string>
|
<string name="settings_title_rating">Рейтинг</string>
|
||||||
<string name="settings_title_replay_gain">Усиление воспроизведения</string>
|
<string name="settings_title_replay_gain">ReplayGain</string>
|
||||||
<string name="settings_title_scrobble">Скроббл</string>
|
<string name="settings_title_scrobble">Скробблинг</string>
|
||||||
<string name="settings_title_skip_min_star_rating">Игнорировать треки по рейтингу</string>
|
<string name="settings_title_skip_min_star_rating">Игнорировать треки по рейтингу</string>
|
||||||
<string name="settings_title_skip_min_star_rating_dialog">Треки с рейтингом:</string>
|
<string name="settings_title_skip_min_star_rating_dialog">Треки с рейтингом:</string>
|
||||||
<string name="settings_title_share">Поделиться</string>
|
<string name="settings_title_share">Общий доступ</string>
|
||||||
<string name="settings_title_syncing">Синхронизации</string>
|
<string name="settings_title_syncing">Синхронизация</string>
|
||||||
<string name="settings_title_transcoding">Транскодирование</string>
|
<string name="settings_title_transcoding">Транскодирование</string>
|
||||||
<string name="settings_title_transcoding_download">Скачивание с транскодированием</string>
|
<string name="settings_title_transcoding_download">Скачивание с транскодированием</string>
|
||||||
<string name="settings_title_ui">UI (Пользовательский интерфейс)</string>
|
<string name="settings_title_ui">Пользовательский интерфейс</string>
|
||||||
<string name="settings_transcoded_download">Перекодированная загрузка</string>
|
<string name="settings_title_ui_landscape_items_per_row">Элементов в строке (альбомная ориентация)</string>
|
||||||
|
<string name="settings_title_ui_landscape_items_per_row_dialog">Количество элементов в строке</string>
|
||||||
|
<string name="settings_transcoded_download">Загрузка с транскодированием</string>
|
||||||
|
|
||||||
<string name="settings_version_title">Версия</string>
|
<string name="settings_version_title">Версия</string>
|
||||||
<string name="settings_wifi_only_summary">Запросить подтверждение пользователя перед потоковой передачей по мобильной сети.</string>
|
<string name="settings_wifi_only_summary">Запрашивать подтверждение перед стримингом через мобильную сеть.</string>
|
||||||
<string name="settings_wifi_only_title">Оповещение о потоковой передаче только через Wi-Fi</string>
|
<string name="settings_wifi_only_title">Предупреждение при стриминге без Wi-Fi</string>
|
||||||
<string name="share_bottom_sheet_copy_link">Копировать ссылку</string>
|
<string name="share_bottom_sheet_copy_link">Копировать ссылку</string>
|
||||||
<string name="share_bottom_sheet_delete">Удалить общий доступ</string>
|
<string name="share_bottom_sheet_delete">Удалить общий доступ</string>
|
||||||
<string name="share_bottom_sheet_update">Обновить общий доступ</string>
|
<string name="share_bottom_sheet_update">Обновить общий доступ</string>
|
||||||
<string name="share_subtitle_item">Срок действия: %1$s</string>
|
<string name="share_subtitle_item">Срок действия: %1$s</string>
|
||||||
|
<string name="share_no_expiration">Никогда</string>
|
||||||
<string name="share_unsupported_error">Общий доступ не поддерживается или не включен</string>
|
<string name="share_unsupported_error">Общий доступ не поддерживается или не включен</string>
|
||||||
|
<string name="asset_link_clipboard_label">Ссылка Tempus</string>
|
||||||
|
<string name="asset_link_label_song">UID трека</string>
|
||||||
|
<string name="asset_link_label_album">UID альбома</string>
|
||||||
|
<string name="asset_link_label_artist">UID артиста</string>
|
||||||
|
<string name="asset_link_label_playlist">UID плейлиста</string>
|
||||||
|
<string name="asset_link_label_genre">UID жанра</string>
|
||||||
|
<string name="asset_link_label_year">UID года</string>
|
||||||
|
<string name="asset_link_label_unknown">UID объекта</string>
|
||||||
|
<string name="asset_link_error_unsupported">Неподдерживаемая ссылка</string>
|
||||||
|
<string name="asset_link_error_song">Не удалось открыть трек</string>
|
||||||
|
<string name="asset_link_error_album">Не удалось открыть альбом</string>
|
||||||
|
<string name="asset_link_error_artist">Не удалось открыть исполнителя</string>
|
||||||
|
<string name="asset_link_error_playlist">Не удалось открыть плейлист</string>
|
||||||
|
<string name="asset_link_chip_text">%1$s • %2$s</string>
|
||||||
|
<string name="asset_link_copied_toast">Скопировано в буфер обмена: %1$s</string>
|
||||||
|
<string name="asset_link_debug_toast">Ссылка объекта: %1$s</string>
|
||||||
<string name="share_update_dialog_hint_description">Описание</string>
|
<string name="share_update_dialog_hint_description">Описание</string>
|
||||||
<string name="share_update_dialog_hint_expiration_date">Дата окончания срока</string>
|
<string name="share_update_dialog_hint_expiration_date">Дата окончания срока</string>
|
||||||
<string name="share_update_dialog_negative_button">Отмена</string>
|
<string name="share_update_dialog_negative_button">Отмена</string>
|
||||||
<string name="share_update_dialog_positive_button">Сохранять</string>
|
<string name="share_update_dialog_positive_button">Сохранить</string>
|
||||||
<string name="share_update_dialog_title">Поделиться</string>
|
<string name="share_update_dialog_title">Поделиться</string>
|
||||||
<string name="song_bottom_sheet_add_to_playlist">Добавить в плейлист</string>
|
<string name="song_bottom_sheet_add_to_playlist">Добавить в плейлист</string>
|
||||||
<string name="song_bottom_sheet_add_to_queue">Добавить в очередь</string>
|
<string name="song_bottom_sheet_add_to_queue">Добавить в очередь</string>
|
||||||
<string name="song_bottom_sheet_download">Скачать</string>
|
<string name="song_bottom_sheet_download">Скачать</string>
|
||||||
<string name="song_bottom_sheet_error_retrieving_album">Ошибка при получении альбома</string>
|
<string name="song_bottom_sheet_error_retrieving_album">Ошибка получения альбома</string>
|
||||||
<string name="song_bottom_sheet_error_retrieving_artist">Не удалось получить исполнителя</string>
|
<string name="song_bottom_sheet_error_retrieving_artist">Ошибка получения исполнителя</string>
|
||||||
<string name="song_bottom_sheet_go_to_album">Перейти в альбом</string>
|
<string name="song_bottom_sheet_go_to_album">Перейти к альбому</string>
|
||||||
<string name="song_bottom_sheet_go_to_artist">Перейти к исполнителю</string>
|
<string name="song_bottom_sheet_go_to_artist">Перейти к артисту</string>
|
||||||
<string name="song_bottom_sheet_instant_mix">Мгновенный микс</string>
|
<string name="song_bottom_sheet_instant_mix">Мгновенный микс</string>
|
||||||
<string name="song_bottom_sheet_play_next">Играть дальше</string>
|
<string name="song_bottom_sheet_play_next">Играть следующим</string>
|
||||||
<string name="song_bottom_sheet_rate">Оценить</string>
|
<string name="song_bottom_sheet_rate">Оценить</string>
|
||||||
<string name="song_bottom_sheet_remove">Удалить</string>
|
<string name="song_bottom_sheet_remove">Удалить с устройства</string>
|
||||||
|
<string name="song_bottom_sheet_remove_from_playlist">Удалить из плейлиста</string>
|
||||||
<string name="song_bottom_sheet_share">Поделиться</string>
|
<string name="song_bottom_sheet_share">Поделиться</string>
|
||||||
<string name="song_list_page_downloaded">Загружено</string>
|
<string name="song_list_page_downloaded">Скачанное</string>
|
||||||
<string name="song_list_page_most_played">Самые популярные треки</string>
|
<string name="song_list_page_most_played">Самые популярные треки</string>
|
||||||
<string name="song_list_page_recently_added">Недавно добавленные треки</string>
|
<string name="song_list_page_recently_added">Недавно добавленные треки</string>
|
||||||
<string name="song_list_page_recently_played">Недавно воспроизведенные треки</string>
|
<string name="song_list_page_recently_played">Недавно воспроизведенные треки</string>
|
||||||
<string name="song_list_page_starred">Помеченные треки</string>
|
<string name="song_list_page_starred">Избранные треки</string>
|
||||||
<string name="song_list_page_top">%1$s\'s Лучшие треки</string>
|
<string name="song_list_page_top">%1$s лучших треков</string>
|
||||||
<string name="song_list_page_year">Год %1$d</string>
|
<string name="song_list_page_year">Год %1$d</string>
|
||||||
<string name="song_subtitle_formatter">%1$s • %2$s %3$s</string>
|
<string name="song_subtitle_formatter">%1$s • %2$s %3$s</string>
|
||||||
<string name="starred_sync_dialog_negative_button">Отмена</string>
|
<string name="starred_sync_dialog_negative_button">Отмена</string>
|
||||||
<string name="starred_sync_dialog_neutral_button">Продолжить</string>
|
<string name="starred_sync_dialog_neutral_button">Продолжить</string>
|
||||||
<string name="starred_sync_dialog_positive_button">Продолжить и скачать</string>
|
<string name="starred_sync_dialog_positive_button">Продолжить и скачать</string>
|
||||||
<string name="starred_sync_dialog_summary">Для скачивания рейтинговых треков может потребоваться большой объем данных.</string>
|
<string name="starred_sync_dialog_summary">Загрузка любимых треков может потребовать значительный объем трафика.</string>
|
||||||
<string name="starred_sync_dialog_title">Синхронизировать отмеченные треки</string>
|
<string name="starred_sync_dialog_title">Синхронизация избранных треков</string>
|
||||||
<string name="starred_album_sync_dialog_summary">Для скачивания рейтинговых альбомов может потребоваться большой объем данных.</string>
|
<string name="starred_artist_sync_dialog_summary">Загрузка любимых исполнителей может потребовать значительный объем трафика.</string>
|
||||||
<string name="starred_album_sync_dialog_title">Синхронизировать отмеченные альбомы</string>
|
<string name="starred_artist_sync_dialog_title">Синхронизация избранных артистов</string>
|
||||||
<string name="streaming_cache_storage_dialog_sub_summary">Чтобы изменения вступили в силу необходимо перезапустить приложение.</string>
|
<string name="starred_album_sync_dialog_summary">Загрузка любимых альбомов может потребовать значительный объем трафика.</string>
|
||||||
<string name="streaming_cache_storage_dialog_summary">Изменение места сохранения кэшированных файлов с одного на другое может привести к удалению файлов в старом хранилище.</string>
|
<string name="starred_album_sync_dialog_title">Синхронизация избранных альбомы</string>
|
||||||
<string name="streaming_cache_storage_dialog_title">Выберите способ сохранения</string>
|
<string name="streaming_cache_storage_dialog_sub_summary">Чтобы изменения вступили в силу, перезапустите приложение.</string>
|
||||||
<string name="streaming_cache_storage_external_dialog_positive_button">Внешний</string>
|
<string name="streaming_cache_storage_dialog_summary">Изменение места хранения кэшированных файлов может привести к удалению ранее сохранённых файлов в старом хранилище.</string>
|
||||||
<string name="streaming_cache_storage_internal_dialog_negative_button">Внутренний</string>
|
<string name="streaming_cache_storage_dialog_title">Выберите хранилище</string>
|
||||||
|
<string name="streaming_cache_storage_external_dialog_positive_button">Внешнее</string>
|
||||||
|
<string name="streaming_cache_storage_internal_dialog_negative_button">Внутреннее</string>
|
||||||
|
|
||||||
<string name="track_info_album">Альбом</string>
|
<string name="track_info_album">Альбом</string>
|
||||||
<string name="track_info_artist">Исполнитель</string>
|
<string name="track_info_artist">Исполнитель</string>
|
||||||
<string name="track_info_bit_depth">Разрядность</string>
|
<string name="track_info_bit_depth">Разрядность</string>
|
||||||
<string name="track_info_bitrate">Битрейт</string>
|
<string name="track_info_bitrate">Битрейт</string>
|
||||||
<string name="track_info_content_type">Тип содержимого</string>
|
<string name="track_info_content_type">Тип контента</string>
|
||||||
<string name="track_info_dialog_positive_button">OK</string>
|
<string name="track_info_dialog_positive_button">OK</string>
|
||||||
<string name="track_info_dialog_title">Информация о треке</string>
|
<string name="track_info_dialog_title">Информация о треке</string>
|
||||||
<string name="track_info_disc_number">Номер диска</string>
|
<string name="track_info_disc_number">Номер диска</string>
|
||||||
<string name="track_info_duration">Продолжительность</string>
|
<string name="track_info_duration">Длина</string>
|
||||||
<string name="track_info_genre">Жанр</string>
|
<string name="track_info_genre">Жанр</string>
|
||||||
<string name="track_info_path">Путь</string>
|
<string name="track_info_path">Путь</string>
|
||||||
<string name="track_info_sampling_rate">Частота сэмплирования</string>
|
<string name="track_info_sampling_rate">Частота дискретизации</string>
|
||||||
<string name="track_info_size">Размер</string>
|
<string name="track_info_size">Размер</string>
|
||||||
<string name="track_info_suffix">Суффикс</string>
|
<string name="track_info_suffix">Расширение</string>
|
||||||
<string name="track_info_summary_downloaded_file">Файл был загружен с использованием API Subsonic. Кодек и битрейт файла остаются неизменными по сравнению с исходным файлом.</string>
|
<string name="track_info_summary_downloaded_file">Файл был загружен через API Subsonic. Кодек и битрейт остаются такими же, как в исходном файле.</string>
|
||||||
<string name="track_info_summary_full_transcode">Приложение запросит сервер перекодировать файл и изменить его битрейт. Запрошенный пользователем кодек: %1$s, с битрейтом %2$s. Любые потенциальные изменения кодека и битрейта файла в выбранном формате будут обрабатываться сервером, который может поддерживать или не поддерживать эту операцию.</string>
|
<string name="track_info_summary_full_transcode">Приложение запросит у сервера транскодирование файла с изменением битрейта. Запрошенный кодек: %1$s, битрейт: %2$s. Возможность изменения кодека и битрейта зависит от сервера и может не поддерживаться.</string>
|
||||||
<string name="track_info_summary_original_file">Приложение будет читать только исходный файл, предоставленный сервером. Приложение явно запросит у сервера неперекодированный файл с битрейтом исходного источника.</string>
|
<string name="track_info_summary_original_file">Приложение воспроизводит оригинальный файл, предоставленный сервером. Серверу отправляется запрос на получение файла без транскодирования и с исходным битрейтом.</string>
|
||||||
<string name="track_info_summary_server_prioritized">Качество воспроизводимого файла остается на усмотрение сервера. Приложение не будет принудительно выбирать кодек и битрейт для любого потенциального перекодирования.</string>
|
<string name="track_info_summary_server_prioritized">Качество воспроизводимого файла остается на усмотрение сервера. Приложение не будет принудительно выбирать кодек или битрейт при транскодировании.</string>
|
||||||
<string name="track_info_summary_transcoding_bitrate">Приложение запросит сервер изменить битрейт файла. Пользователь запросил битрейт %1$s, при этом кодек исходного файла останется прежним. Любые изменения битрейта файла в выбранном формате будут выполняться сервером, который может поддерживать или не поддерживать эту операцию.</string>
|
<string name="track_info_summary_transcoding_bitrate">Приложение запросит у сервера изменение битрейта файла. Запрошенный битрейт: %1$s, кодек файла останется прежним. Возможность изменения битрейта файла зависит от сервера, который может поддерживать или не поддерживать эту операцию.</string>
|
||||||
<string name="track_info_summary_transcoding_codec">Приложение запросит сервер перекодировать файл. Запрошенный пользователем кодек — %1$s, а битрейт будет такой же, как у исходного файла. Потенциальное перекодирование файла в выбранный формат зависит от сервера, поскольку он может поддерживать или не поддерживать эту операцию.</string>
|
<string name="track_info_summary_transcoding_codec">Приложение запросит у сервера транскодирование файла. Запрошенный кодек: %1$s, битрейт файла останется прежним. Возможность транскодирования файла в выбранный формат зависит от сервера, который может поддерживать или не поддерживать эту операцию.</string>
|
||||||
<string name="track_info_title">Заголовок</string>
|
<string name="track_info_title">Заголовок</string>
|
||||||
<string name="track_info_track_number">Номер трека</string>
|
<string name="track_info_track_number">Номер трека</string>
|
||||||
<string name="track_info_transcoded_content_type">Тип транскодированного контента</string>
|
<string name="track_info_station">Станция</string>
|
||||||
<string name="track_info_transcoded_suffix">Транскодированный суффикс</string>
|
<string name="track_info_transcoded_content_type">Тип транскод. файла</string>
|
||||||
|
<string name="track_info_transcoded_suffix">Расширение транскод. файла</string>
|
||||||
<string name="track_info_year">Год</string>
|
<string name="track_info_year">Год</string>
|
||||||
<string name="undraw_page">Развернуть</string>
|
|
||||||
<string name="undraw_thanks">Особая благодарность — команде unDraw, без иллюстраций которой мы не смогли бы сделать это приложение красивее.</string>
|
<string name="undraw_thanks">Особая благодарность команде unDraw за иллюстрации, которые помогли сделать приложение красивее</string>
|
||||||
<string name="undraw_url">https://undraw.co/</string>
|
|
||||||
|
<string name="widget_label">Tempus Widget</string>
|
||||||
|
<string name="widget_not_playing">Ничего не воспроизводится</string>
|
||||||
|
<string name="widget_placeholder_subtitle">Открыть Tempus</string>
|
||||||
|
<string name="widget_time_elapsed_placeholder">0:00</string>
|
||||||
|
<string name="widget_time_duration_placeholder">0:00</string>
|
||||||
|
<string name="widget_content_desc_album_art">Обложка альбома</string>
|
||||||
|
<string name="widget_content_desc_play_pause">Плей или пауза</string>
|
||||||
|
<string name="widget_content_desc_next">Следующий трек</string>
|
||||||
|
<string name="widget_content_desc_prev">Предыдущий трек</string>
|
||||||
|
<string name="widget_content_desc_shuffle">Перемешивание</string>
|
||||||
|
<string name="widget_content_desc_repeat">Изменить режим повтора</string>
|
||||||
<plurals name="home_sync_starred_albums_count">
|
<plurals name="home_sync_starred_albums_count">
|
||||||
<item quantity="one">Альбомов для синхронизации: %d</item>
|
<item quantity="one">Альбомов для синхронизации: %d</item>
|
||||||
<item quantity="other">Альбомов для синхронизации: %d</item>
|
<item quantity="other">Альбомов для синхронизации: %d</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
<plurals name="home_sync_starred_artists_count">
|
||||||
|
<item quantity="one">Исполнителей для синхронизации: %d</item>
|
||||||
|
<item quantity="other">Исполнителей для синхронизации: %d</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="songs_download_started">
|
||||||
|
<item quantity="one">Скачивание %d трека</item>
|
||||||
|
<item quantity="other">Скачивание %d треков</item>
|
||||||
|
</plurals>
|
||||||
|
<string name="equalizer_fragment_title">Эквалайзер</string>
|
||||||
|
<string name="equalizer_reset">Сброс</string>
|
||||||
|
<string name="equalizer_enable">Включить</string>
|
||||||
|
<string name="equalizer_not_supported">Не поддерживается на этом устройстве</string>
|
||||||
|
<string name="settings_app_equalizer">Эквалайзер</string>
|
||||||
|
<string name="settings_app_equalizer_summary">Открыть встроенный эквалайзер</string>
|
||||||
|
|
||||||
|
<string name="settings_album_detail">Показывать информацию об альбоме</string>
|
||||||
|
<string name="settings_album_detail_summary">Если включено, на странице альбома отображаются дополнительные сведения: жанр, количество треков и т.д.</string>
|
||||||
|
<string name="settings_artist_sort_by_album_count">Сортировать артистов по количеству альбомов</string>
|
||||||
|
<string name="settings_artist_sort_by_album_count_summary">Если включено, исполнители сортируются по количеству альбомов. Если отключено - по имени.</string>
|
||||||
|
|
||||||
|
<string name="folder_play_collecting">Сканирование папки…</string>
|
||||||
|
<string name="folder_play_playing">Воспроизведение %d треков</string>
|
||||||
|
<string name="folder_play_no_songs">В папке нет треков</string>
|
||||||
|
|
||||||
|
<string name="search_sort_title">Сортировать недавние поиски по времени</string>
|
||||||
|
<string name="search_sort_summary">Если включено, поиски сортируются по времени. Если отключено - по имени.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
1
app/src/main/res/values-zh-rCN
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
values-zh
|
||||||
257
app/src/main/res/values-zh-rTW/arrays.xml
Normal file
@@ -0,0 +1,257 @@
|
|||||||
|
<resources>
|
||||||
|
<string-array name="theme_list_titles">
|
||||||
|
<item>淺色</item>
|
||||||
|
<item>深色</item>
|
||||||
|
<item>跟隨系統</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="theme_list_values">
|
||||||
|
<item>light</item>
|
||||||
|
<item>dark</item>
|
||||||
|
<item>default</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="pref_cache_size_titles">
|
||||||
|
<item>高</item>
|
||||||
|
<item>中</item>
|
||||||
|
<item>低</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="pref_cache_size_values">
|
||||||
|
<item>500</item>
|
||||||
|
<item>250</item>
|
||||||
|
<item>125</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="pref_image_size_titles">
|
||||||
|
<item>高</item>
|
||||||
|
<item>中</item>
|
||||||
|
<item>低</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="pref_image_size_values">
|
||||||
|
<item>-1</item>
|
||||||
|
<item>500</item>
|
||||||
|
<item>300</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="streaming_cache_size_titles">
|
||||||
|
<item>禁用</item>
|
||||||
|
<item>128 MiB</item>
|
||||||
|
<item>256 MiB</item>
|
||||||
|
<item>512 MiB</item>
|
||||||
|
<item>1024 MiB</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="streaming_cache_size_values">
|
||||||
|
<item>0</item>
|
||||||
|
<item>128</item>
|
||||||
|
<item>256</item>
|
||||||
|
<item>512</item>
|
||||||
|
<item>1024</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="max_bitrate_wifi_list_titles">
|
||||||
|
<item>原始</item>
|
||||||
|
<item>32 kbps</item>
|
||||||
|
<item>48 kbps</item>
|
||||||
|
<item>64 kbps</item>
|
||||||
|
<item>80 kbps</item>
|
||||||
|
<item>96 kbps</item>
|
||||||
|
<item>112 kbps</item>
|
||||||
|
<item>128 kbps</item>
|
||||||
|
<item>160 kbps</item>
|
||||||
|
<item>192 kbps</item>
|
||||||
|
<item>256 kbps</item>
|
||||||
|
<item>320 kbps</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="max_bitrate_wifi_list_values">
|
||||||
|
<item>0</item>
|
||||||
|
<item>32</item>
|
||||||
|
<item>48</item>
|
||||||
|
<item>64</item>
|
||||||
|
<item>80</item>
|
||||||
|
<item>96</item>
|
||||||
|
<item>112</item>
|
||||||
|
<item>128</item>
|
||||||
|
<item>160</item>
|
||||||
|
<item>192</item>
|
||||||
|
<item>256</item>
|
||||||
|
<item>320</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="max_bitrate_mobile_list_titles">
|
||||||
|
<item>原始</item>
|
||||||
|
<item>32 kbps</item>
|
||||||
|
<item>48 kbps</item>
|
||||||
|
<item>64 kbps</item>
|
||||||
|
<item>80 kbps</item>
|
||||||
|
<item>96 kbps</item>
|
||||||
|
<item>112 kbps</item>
|
||||||
|
<item>128 kbps</item>
|
||||||
|
<item>160 kbps</item>
|
||||||
|
<item>192 kbps</item>
|
||||||
|
<item>256 kbps</item>
|
||||||
|
<item>320 kbps</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="max_bitrate_mobile_list_values">
|
||||||
|
<item>0</item>
|
||||||
|
<item>32</item>
|
||||||
|
<item>48</item>
|
||||||
|
<item>64</item>
|
||||||
|
<item>80</item>
|
||||||
|
<item>96</item>
|
||||||
|
<item>112</item>
|
||||||
|
<item>128</item>
|
||||||
|
<item>160</item>
|
||||||
|
<item>192</item>
|
||||||
|
<item>256</item>
|
||||||
|
<item>320</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="max_bitrate_download_list_titles">
|
||||||
|
<item>原始</item>
|
||||||
|
<item>32 kbps</item>
|
||||||
|
<item>48 kbps</item>
|
||||||
|
<item>64 kbps</item>
|
||||||
|
<item>80 kbps</item>
|
||||||
|
<item>96 kbps</item>
|
||||||
|
<item>112 kbps</item>
|
||||||
|
<item>128 kbps</item>
|
||||||
|
<item>160 kbps</item>
|
||||||
|
<item>192 kbps</item>
|
||||||
|
<item>256 kbps</item>
|
||||||
|
<item>320 kbps</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="max_bitrate_download_list_values">
|
||||||
|
<item>0</item>
|
||||||
|
<item>32</item>
|
||||||
|
<item>48</item>
|
||||||
|
<item>64</item>
|
||||||
|
<item>80</item>
|
||||||
|
<item>96</item>
|
||||||
|
<item>112</item>
|
||||||
|
<item>128</item>
|
||||||
|
<item>160</item>
|
||||||
|
<item>192</item>
|
||||||
|
<item>256</item>
|
||||||
|
<item>320</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="audio_transcode_format_wifi_list_titles">
|
||||||
|
<item>播放原始</item>
|
||||||
|
<item>Opus</item>
|
||||||
|
<item>AAC</item>
|
||||||
|
<item>Mp3</item>
|
||||||
|
<item>Flac</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="audio_transcode_format_wifi_list_values">
|
||||||
|
<item>raw</item>
|
||||||
|
<item>opus</item>
|
||||||
|
<item>aac</item>
|
||||||
|
<item>mp3</item>
|
||||||
|
<item>flac</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="audio_transcode_format_mobile_list_titles">
|
||||||
|
<item>播放原始</item>
|
||||||
|
<item>Opus</item>
|
||||||
|
<item>AAC</item>
|
||||||
|
<item>Mp3</item>
|
||||||
|
<item>Flac</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="audio_transcode_format_mobile_list_values">
|
||||||
|
<item>raw</item>
|
||||||
|
<item>opus</item>
|
||||||
|
<item>aac</item>
|
||||||
|
<item>mp3</item>
|
||||||
|
<item>flac</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="audio_transcode_format_download_list_titles">
|
||||||
|
<item>下載原始</item>
|
||||||
|
<item>Opus</item>
|
||||||
|
<item>AAC</item>
|
||||||
|
<item>Mp3</item>
|
||||||
|
<item>Flac</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="audio_transcode_format_download_list_values">
|
||||||
|
<item>raw</item>
|
||||||
|
<item>opus</item>
|
||||||
|
<item>aac</item>
|
||||||
|
<item>mp3</item>
|
||||||
|
<item>flac</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="queue_syncing_countdown_titles">
|
||||||
|
<item>10秒</item>
|
||||||
|
<item>5秒</item>
|
||||||
|
<item>2秒</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="queue_syncing_countdown_values">
|
||||||
|
<item>10</item>
|
||||||
|
<item>5</item>
|
||||||
|
<item>2</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="rounded_corner_size_titles">
|
||||||
|
<item>高</item>
|
||||||
|
<item>中</item>
|
||||||
|
<item>低</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="rounded_corner_size_values">
|
||||||
|
<item>18</item>
|
||||||
|
<item>12</item>
|
||||||
|
<item>6</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="replay_gain_titles">
|
||||||
|
<item>禁用</item>
|
||||||
|
<item>曲目</item>
|
||||||
|
<item>專輯</item>
|
||||||
|
<item>自動</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="replay_gain_values">
|
||||||
|
<item>disabled</item>
|
||||||
|
<item>track</item>
|
||||||
|
<item>album</item>
|
||||||
|
<item>auto</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="transcoded_download_option_list_titles">
|
||||||
|
<item>不轉碼</item>
|
||||||
|
<item>伺服器設定</item>
|
||||||
|
<item>Wi-Fi轉碼設定</item>
|
||||||
|
<item>行動資料轉碼設定</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="transcoded_download_option_list_values">
|
||||||
|
<item>0</item>
|
||||||
|
<item>1</item>
|
||||||
|
<item>2</item>
|
||||||
|
<item>3</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="buffering_strategy_titles">
|
||||||
|
<item>最小</item>
|
||||||
|
<item>適中</item>
|
||||||
|
<item>積極</item>
|
||||||
|
<item>極端</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="buffering_strategy_values">
|
||||||
|
<item>.1</item>
|
||||||
|
<item>1</item>
|
||||||
|
<item>4</item>
|
||||||
|
<item>8</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="skip_min_star_rating_titles">
|
||||||
|
<item>不篩選評分</item>
|
||||||
|
<item>1 星及以上</item>
|
||||||
|
<item>2 星及以上</item>
|
||||||
|
<item>3 星及以上</item>
|
||||||
|
<item>4 星及以上</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="skip_min_star_rating_values">
|
||||||
|
<item>0</item>
|
||||||
|
<item>1</item>
|
||||||
|
<item>2</item>
|
||||||
|
<item>3</item>
|
||||||
|
<item>4</item>
|
||||||
|
</string-array>
|
||||||
|
</resources>
|
||||||
550
app/src/main/res/values-zh-rTW/strings.xml
Normal file
@@ -0,0 +1,550 @@
|
|||||||
|
<resources>
|
||||||
|
<string name="activity_battery_optimizations_conclusion">如果遇到問題,請存取 https://dontkillmyapp.com。 省電優化選項可能會影響應用程式的性能,網站上提供瞭如何禁用這些選項的詳細說明。</string>
|
||||||
|
<string name="activity_battery_optimizations_summary">請禁用針對鎖定畫面播放的電池優化。</string>
|
||||||
|
<string name="activity_battery_optimizations_title">電池優化</string>
|
||||||
|
<string name="activity_info_offline_mode">離線模式</string>
|
||||||
|
<string name="album_bottom_sheet_add_to_playlist">新增到播放清單</string>
|
||||||
|
<string name="album_bottom_sheet_add_to_queue">新增到序列</string>
|
||||||
|
<string name="album_bottom_sheet_download_all">全部下載</string>
|
||||||
|
<string name="album_bottom_sheet_go_to_artist">查看該藝術家</string>
|
||||||
|
<string name="album_bottom_sheet_instant_mix">即時混聽</string>
|
||||||
|
<string name="album_bottom_sheet_play_next">下一首播放</string>
|
||||||
|
<string name="album_bottom_sheet_remove_all">移除所有</string>
|
||||||
|
<string name="album_bottom_sheet_share">分享</string>
|
||||||
|
<string name="album_bottom_sheet_shuffle">隨機播放</string>
|
||||||
|
<string name="album_catalogue_title">專輯</string>
|
||||||
|
<string name="album_catalogue_title_expanded">瀏覽專輯</string>
|
||||||
|
<string name="album_error_retrieving_artist">檢索藝術家時出錯</string>
|
||||||
|
<string name="album_list_page_downloaded">已下載的專輯</string>
|
||||||
|
<string name="album_list_page_most_played">最常播放的專輯</string>
|
||||||
|
<string name="album_list_page_new_releases">新發行的專輯</string>
|
||||||
|
<string name="album_list_page_recently_added">最近新增的專輯</string>
|
||||||
|
<string name="album_list_page_recently_played">最近播放的專輯</string>
|
||||||
|
<string name="album_list_page_starred">收藏的專輯</string>
|
||||||
|
<string name="album_list_page_title">專輯</string>
|
||||||
|
<string name="album_page_extra_info_button">更多相似</string>
|
||||||
|
<string name="album_page_play_button">播放</string>
|
||||||
|
<string name="album_page_release_date_label">發行日期:%1$s</string>
|
||||||
|
<string name="album_page_release_dates_label">發行日期:%1$s(原版發行於 %2$s)</string>
|
||||||
|
<string name="album_page_shuffle_button">隨機播放</string>
|
||||||
|
<string name="album_page_tracks_count_and_duration">%1$d 首歌曲 • %2$d 分鐘</string>
|
||||||
|
<string name="app_name">Tempus</string>
|
||||||
|
<string name="artist_adapter_radio_station_starting">正在搜尋...</string>
|
||||||
|
<string name="artist_bottom_sheet_instant_mix">即時混聽</string>
|
||||||
|
<string name="artist_bottom_sheet_shuffle">隨機播放</string>
|
||||||
|
<string name="artist_catalogue_title">藝術家</string>
|
||||||
|
<string name="artist_catalogue_title_expanded">瀏覽藝術家</string>
|
||||||
|
<string name="artist_error_retrieving_radio">檢索藝術家的電臺時出錯</string>
|
||||||
|
<string name="artist_error_retrieving_tracks">檢索藝術家歌曲時出錯</string>
|
||||||
|
<string name="artist_list_page_downloaded">已下載的藝術家</string>
|
||||||
|
<string name="artist_list_page_starred">收藏的藝術家</string>
|
||||||
|
<string name="artist_list_page_title">藝術家</string>
|
||||||
|
<string name="artist_page_radio_button">電臺</string>
|
||||||
|
<string name="artist_page_shuffle_button">隨機播放</string>
|
||||||
|
<string name="artist_page_switch_layout_button">切換佈局</string>
|
||||||
|
<string name="artist_page_title_album_more_like_this_button">更多類似</string>
|
||||||
|
<string name="artist_page_title_album_section">專輯</string>
|
||||||
|
<string name="artist_page_title_biography_more_button">更多</string>
|
||||||
|
<string name="artist_page_title_biography_section">藝術家簡介</string>
|
||||||
|
<string name="artist_page_title_most_streamed_song_section">最常播放的歌曲</string>
|
||||||
|
<string name="artist_page_title_most_streamed_song_see_all_button">查看全部</string>
|
||||||
|
<string name="asset_link_chip_text">%1$s • %2$s</string>
|
||||||
|
<string name="asset_link_clipboard_label">Tempus 資源連結</string>
|
||||||
|
<string name="asset_link_copied_toast">已將 %1$s 複製到剪貼簿</string>
|
||||||
|
<string name="asset_link_debug_toast">資源連結:%1$s</string>
|
||||||
|
<string name="asset_link_error_album">無法開啟該專輯</string>
|
||||||
|
<string name="asset_link_error_artist">無法開啟該藝術家頁</string>
|
||||||
|
<string name="asset_link_error_playlist">無法開啟該播放清單</string>
|
||||||
|
<string name="asset_link_error_song">無法開啟該歌曲</string>
|
||||||
|
<string name="asset_link_error_unsupported">不支援的資源連結</string>
|
||||||
|
<string name="asset_link_label_album">專輯 UID</string>
|
||||||
|
<string name="asset_link_label_artist">藝術家 UID</string>
|
||||||
|
<string name="asset_link_label_genre">流派 UID</string>
|
||||||
|
<string name="asset_link_label_playlist">播放清單 UID</string>
|
||||||
|
<string name="asset_link_label_song">歌曲 UID</string>
|
||||||
|
<string name="asset_link_label_unknown">資源 UID</string>
|
||||||
|
<string name="asset_link_label_year">年份 UID</string>
|
||||||
|
<string name="battery_optimization_negative_button">忽略</string>
|
||||||
|
<string name="battery_optimization_neutral_button">不再詢問</string>
|
||||||
|
<string name="battery_optimization_positive_button">禁用</string>
|
||||||
|
<string name="cast_expanded_controller_loading">載入中...</string>
|
||||||
|
<string name="connection_alert_dialog_negative_button">取消</string>
|
||||||
|
<string name="connection_alert_dialog_neutral_button">啟用流量節省</string>
|
||||||
|
<string name="connection_alert_dialog_positive_button">確定</string>
|
||||||
|
<string name="connection_alert_dialog_summary">已限制通過 Wi-Fi 以外的連接存取 Subsonic 伺服器。 欲阻止此警告對話框再次出現,請在應用程式設定中禁用連接檢查。</string>
|
||||||
|
<string name="connection_alert_dialog_title">Wi-Fi 網路未連接</string>
|
||||||
|
<string name="content_description_shuffle_button">隨機</string>
|
||||||
|
<string name="delete_download_storage_dialog_negative_button">取消</string>
|
||||||
|
<string name="delete_download_storage_dialog_positive_button">繼續</string>
|
||||||
|
<string name="delete_download_storage_dialog_summary">請注意,繼續執行此操作將永久刪除從所有伺服器下載的所有已儲存的項目。</string>
|
||||||
|
<string name="delete_download_storage_dialog_title">刪除已儲存的項目</string>
|
||||||
|
<string name="description_empty_title">沒有可用的歌詞</string>
|
||||||
|
<string name="disc_titlefull">第 %1$s 張光碟 - %2$s</string>
|
||||||
|
<string name="disc_titleless">第 %1$s 張光碟</string>
|
||||||
|
<string name="download_directory_dialog_negative_button">取消</string>
|
||||||
|
<string name="download_directory_dialog_positive_button">下載</string>
|
||||||
|
<string name="download_directory_dialog_summary">該資料夾中的所有歌曲將被下載。子資料夾中的歌曲將不會被下載。</string>
|
||||||
|
<string name="download_directory_dialog_title">下載歌曲</string>
|
||||||
|
<string name="download_directory_set">設定歌曲下載位置</string>
|
||||||
|
<string name="download_info_empty_subtitle">下載歌曲後,您可以在這裡找到它</string>
|
||||||
|
<string name="download_info_empty_title">還沒有下載!</string>
|
||||||
|
<string name="download_item_multiple_subtitle_formatter">%1$s • %2$s 個項目</string>
|
||||||
|
<string name="download_item_single_subtitle_formatter">%1$s 個項目</string>
|
||||||
|
<string name="download_refresh_button_content_description">刷新下載項</string>
|
||||||
|
<string name="download_refresh_no_changes">沒有遺漏的下載項。</string>
|
||||||
|
<string name="download_refresh_no_directory">設定下載目錄以刷新下載內容。</string>
|
||||||
|
<plurals name="download_refresh_removed">
|
||||||
|
<item quantity="one">已移除 %d 個缺失的下載項。</item>
|
||||||
|
<item quantity="other">已移除 %d 個缺失的下載項。</item>
|
||||||
|
</plurals>
|
||||||
|
<string name="download_shuffle_all_subtitle">隨機播放全部</string>
|
||||||
|
<string name="download_storage_dialog_sub_summary">要使更改生效,請重新啟動應用程式。</string>
|
||||||
|
<string name="download_storage_dialog_summary">更改已下載檔案的目錄將會立即刪除以前已下載的所有檔案。</string>
|
||||||
|
<string name="download_storage_dialog_title">選擇儲存選項</string>
|
||||||
|
<string name="download_storage_directory_dialog_neutral_button">目錄</string>
|
||||||
|
<string name="download_storage_external_dialog_positive_button">外部</string>
|
||||||
|
<string name="download_storage_internal_dialog_negative_button">內部</string>
|
||||||
|
<string name="download_title_section">下載</string>
|
||||||
|
<string name="downloaded_bottom_sheet_add_to_queue">新增到序列</string>
|
||||||
|
<string name="downloaded_bottom_sheet_play_next">下一首播放</string>
|
||||||
|
<string name="downloaded_bottom_sheet_remove">移除</string>
|
||||||
|
<string name="downloaded_bottom_sheet_remove_all">移除所有</string>
|
||||||
|
<string name="downloaded_bottom_sheet_shuffle">隨機播放</string>
|
||||||
|
<string name="empty_string" />
|
||||||
|
<string name="equalizer_enable">啟用</string>
|
||||||
|
<string name="equalizer_fragment_title">均衡器</string>
|
||||||
|
<string name="equalizer_not_supported">此設備不支援</string>
|
||||||
|
<string name="equalizer_reset">重置</string>
|
||||||
|
<string name="error_required">必需</string>
|
||||||
|
<string name="error_server_prefix">必須是 http 或 https 前綴</string>
|
||||||
|
<string name="exo_controls_heart_off_description">取消收藏</string>
|
||||||
|
<string name="exo_controls_heart_on_description">收藏</string>
|
||||||
|
<string name="exo_download_notification_channel_name">下載</string>
|
||||||
|
<string name="filter_artist">篩選藝術家</string>
|
||||||
|
<string name="filter_info_selection">選擇兩個或多個過濾器</string>
|
||||||
|
<string name="filter_title">篩選</string>
|
||||||
|
<string name="filter_title_expanded">篩選流派</string>
|
||||||
|
<string name="folder_play_collecting">正在讀取資料夾中的歌曲...</string>
|
||||||
|
<string name="folder_play_no_songs">資料夾內未發現歌曲</string>
|
||||||
|
<string name="folder_play_playing">正在播放 %d 首歌曲</string>
|
||||||
|
<string name="generic_list_page_count">(%1$d)</string>
|
||||||
|
<string name="generic_list_page_count_unknown">(+%1$d)</string>
|
||||||
|
<string name="genre_catalogue_title">流派目錄</string>
|
||||||
|
<string name="genre_catalogue_title_expanded">瀏覽流派</string>
|
||||||
|
<string name="github_update_dialog_negative_button">稍後提醒</string>
|
||||||
|
<string name="github_update_dialog_neutral_button">支援項目</string>
|
||||||
|
<string name="github_update_dialog_positive_button">立即下載</string>
|
||||||
|
<string name="github_update_dialog_summary">GitHub 上發佈了新版本。</string>
|
||||||
|
<string name="github_update_dialog_title">有可用更新</string>
|
||||||
|
<string name="home_option_reorganize">定製首頁</string>
|
||||||
|
<string name="home_rearrangement_dialog_negative_button">取消</string>
|
||||||
|
<string name="home_rearrangement_dialog_neutral_button">重置</string>
|
||||||
|
<string name="home_rearrangement_dialog_positive_button">儲存</string>
|
||||||
|
<string name="home_rearrangement_dialog_subtitle">請重啟應用程式以套用更改。</string>
|
||||||
|
<string name="home_rearrangement_dialog_title">首頁排序</string>
|
||||||
|
<string name="home_section_music">音樂</string>
|
||||||
|
<string name="home_section_podcast">播客</string>
|
||||||
|
<string name="home_section_radio">電臺</string>
|
||||||
|
<string name="home_subtitle_best_of">您最喜歡的藝術家的熱門歌曲</string>
|
||||||
|
<string name="home_subtitle_made_for_you">從您喜歡的歌曲開始混聽</string>
|
||||||
|
<string name="home_subtitle_new_internet_radio_station">新增新的電臺</string>
|
||||||
|
<string name="home_subtitle_new_podcast_channel">新增新的播客頻道</string>
|
||||||
|
<plurals name="home_sync_starred_albums_count">
|
||||||
|
<item quantity="one">%d 個待同步專輯</item>
|
||||||
|
<item quantity="other">%d 個待同步專輯</item>
|
||||||
|
</plurals>
|
||||||
|
<string name="home_sync_starred_albums_subtitle">標記為收藏的專輯可離線使用</string>
|
||||||
|
<string name="home_sync_starred_albums_title">同步收藏的專輯</string>
|
||||||
|
<string name="home_sync_starred_artists_subtitle">你收藏的藝術家有未下載的歌曲</string>
|
||||||
|
<string name="home_sync_starred_artists_title">同步收藏的藝術家</string>
|
||||||
|
<plurals name="home_sync_starred_artists_count">
|
||||||
|
<item quantity="one">%d 個待同步藝術家</item>
|
||||||
|
<item quantity="other">%d 個待同步藝術家</item>
|
||||||
|
</plurals>
|
||||||
|
<string name="home_sync_starred_cancel">取消</string>
|
||||||
|
<string name="home_sync_starred_download">下載</string>
|
||||||
|
<plurals name="home_sync_starred_songs_count">
|
||||||
|
<item quantity="one">%d 首待同步歌曲</item>
|
||||||
|
<item quantity="other">%d 首待同步歌曲</item>
|
||||||
|
</plurals>
|
||||||
|
<string name="home_sync_starred_subtitle">下載這些歌曲可能需要大量行動資料流量</string>
|
||||||
|
<string name="home_sync_starred_title">似乎有一些收藏的歌曲需要同步</string>
|
||||||
|
<string name="home_title_best_of">最佳</string>
|
||||||
|
<string name="home_title_discovery">發現</string>
|
||||||
|
<string name="home_title_discovery_shuffle_all_button">隨機播放全部</string>
|
||||||
|
<string name="home_title_flashback">重溫舊曲</string>
|
||||||
|
<string name="home_title_internet_radio_station">網路廣播電臺</string>
|
||||||
|
<string name="home_title_last_month">上月</string>
|
||||||
|
<string name="home_title_last_played">最近播放</string>
|
||||||
|
<string name="home_title_last_played_see_all_button">查看全部</string>
|
||||||
|
<string name="home_title_last_week">上週</string>
|
||||||
|
<string name="home_title_last_year">去年</string>
|
||||||
|
<string name="home_title_made_for_you">為您定製</string>
|
||||||
|
<string name="home_title_most_played">最常播放</string>
|
||||||
|
<string name="home_title_most_played_see_all_button">查看全部</string>
|
||||||
|
<string name="home_title_new_releases">新發行</string>
|
||||||
|
<string name="home_title_newest_podcasts">最新播客</string>
|
||||||
|
<string name="home_title_pinned_playlists">播放清單</string>
|
||||||
|
<string name="home_title_podcast_channels">頻道</string>
|
||||||
|
<string name="home_title_podcast_channels_see_all_button">查看全部</string>
|
||||||
|
<string name="home_title_radio_station">廣播電臺</string>
|
||||||
|
<string name="home_title_recently_added">最近新增</string>
|
||||||
|
<string name="home_title_recently_added_see_all_button">查看全部</string>
|
||||||
|
<string name="home_title_shares">分享</string>
|
||||||
|
<string name="home_title_starred_albums">★ 收藏的專輯</string>
|
||||||
|
<string name="home_title_starred_albums_see_all_button">查看全部</string>
|
||||||
|
<string name="home_title_starred_artists">★ 收藏的藝術家</string>
|
||||||
|
<string name="home_title_starred_artists_see_all_button">查看全部</string>
|
||||||
|
<string name="home_title_starred_tracks">★ 收藏的歌曲</string>
|
||||||
|
<string name="home_title_starred_tracks_see_all_button">查看全部</string>
|
||||||
|
<string name="home_title_top_songs">你最喜歡的歌曲</string>
|
||||||
|
<string name="label_dot_separator" translatable="false">•</string>
|
||||||
|
<string name="label_placeholder" translatable="false">--</string>
|
||||||
|
<string name="library_title_album">專輯</string>
|
||||||
|
<string name="library_title_album_see_all_button">查看全部</string>
|
||||||
|
<string name="library_title_artist">藝術家</string>
|
||||||
|
<string name="library_title_artist_see_all_button">查看全部</string>
|
||||||
|
<string name="library_title_genre">流派</string>
|
||||||
|
<string name="library_title_genre_see_all_button">查看全部</string>
|
||||||
|
<string name="library_title_music_folder">音樂資料夾</string>
|
||||||
|
<string name="library_title_playlist">播放清單</string>
|
||||||
|
<string name="library_title_playlist_see_all_button">查看全部</string>
|
||||||
|
<string name="login_empty">尚未新增伺服器</string>
|
||||||
|
<string name="login_title">Subsonic 伺服器</string>
|
||||||
|
<string name="login_title_expanded">Subsonic 伺服器</string>
|
||||||
|
<string name="media_route_menu_title">投送</string>
|
||||||
|
<string name="menu_add_button">新增</string>
|
||||||
|
<string name="menu_add_to_playlist_button">新增到播放清單</string>
|
||||||
|
<string name="menu_download_all_button">全部下載</string>
|
||||||
|
<string name="menu_download_label">下載</string>
|
||||||
|
<string name="menu_filter_all">全部</string>
|
||||||
|
<string name="menu_filter_download">已下載</string>
|
||||||
|
<string name="menu_group_by_album">專輯</string>
|
||||||
|
<string name="menu_group_by_artist">藝術家</string>
|
||||||
|
<string name="menu_group_by_genre">流派</string>
|
||||||
|
<string name="menu_group_by_track">歌曲</string>
|
||||||
|
<string name="menu_group_by_year">年份</string>
|
||||||
|
<string name="menu_home_label">首頁</string>
|
||||||
|
<string name="menu_last_month_name">上月</string>
|
||||||
|
<string name="menu_last_week_name">上週</string>
|
||||||
|
<string name="menu_last_year_name">去年</string>
|
||||||
|
<string name="menu_library_label">曲庫</string>
|
||||||
|
<string name="menu_pin_button">新增到首頁</string>
|
||||||
|
<string name="menu_rate_album">專輯評分</string>
|
||||||
|
<string name="menu_search_button">搜尋</string>
|
||||||
|
<string name="menu_settings_button">設定</string>
|
||||||
|
<string name="menu_sort_album_count">專輯數量</string>
|
||||||
|
<string name="menu_sort_artist">藝術家</string>
|
||||||
|
<string name="menu_sort_least_recently_starred">最早收藏</string>
|
||||||
|
<string name="menu_sort_most_played">最多播放</string>
|
||||||
|
<string name="menu_sort_most_recently_starred">最近收藏</string>
|
||||||
|
<string name="menu_sort_name">名稱</string>
|
||||||
|
<string name="menu_sort_random">隨機</string>
|
||||||
|
<string name="menu_sort_recently_added">最近新增</string>
|
||||||
|
<string name="menu_sort_recently_played">最近播放</string>
|
||||||
|
<string name="menu_sort_year">年份</string>
|
||||||
|
<string name="menu_unpin_button">從首頁移除</string>
|
||||||
|
<string name="player_lyrics_download_content_description">下載離線歌詞</string>
|
||||||
|
<string name="player_lyrics_download_failure">暫無歌詞可供下載。</string>
|
||||||
|
<string name="player_lyrics_download_success">離線歌詞已儲存。</string>
|
||||||
|
<string name="player_lyrics_downloaded_content_description">已下載的離線歌詞</string>
|
||||||
|
<string name="player_playback_speed">%1$.2fx</string>
|
||||||
|
<string name="player_queue_clean_all_button">清空序列</string>
|
||||||
|
<string name="player_queue_load_queue">載入序列</string>
|
||||||
|
<string name="player_queue_save_queue_success">儲存序列</string>
|
||||||
|
<string name="player_queue_save_to_playlist">儲存序列到播放清單</string>
|
||||||
|
<string name="player_server_priority">伺服器優先級</string>
|
||||||
|
<string name="player_transcoding">正在轉碼</string>
|
||||||
|
<string name="player_transcoding_requested">已請求轉碼</string>
|
||||||
|
<string name="player_unknown_format">未知格式</string>
|
||||||
|
<string name="playlist_catalogue_title">播放清單目錄</string>
|
||||||
|
<string name="playlist_catalogue_title_expanded">瀏覽播放清單</string>
|
||||||
|
<string name="playlist_chooser_dialog_empty">尚未建立播放清單</string>
|
||||||
|
<string name="playlist_chooser_dialog_cancel_button">取消</string>
|
||||||
|
<string name="playlist_chooser_dialog_create_button">新建</string>
|
||||||
|
<string name="playlist_chooser_dialog_title">新增到播放清單</string>
|
||||||
|
<string name="playlist_chooser_dialog_toast_add_failure">未能將歌曲新增到播放清單</string>
|
||||||
|
<string name="playlist_chooser_dialog_toast_add_success">將歌曲新增到播放清單</string>
|
||||||
|
<string name="playlist_chooser_dialog_toast_all_skipped">所有歌曲已存在,無需重複新增</string>
|
||||||
|
<string name="playlist_counted_tracks">%1$d 首歌曲 • %2$s</string>
|
||||||
|
<string name="playlist_duration">時長 • %1$s</string>
|
||||||
|
<string name="playlist_editor_dialog_action_delete_toast">長按刪除</string>
|
||||||
|
<string name="playlist_editor_dialog_hint_name">播放清單名稱</string>
|
||||||
|
<string name="playlist_editor_dialog_negative_button">取消</string>
|
||||||
|
<string name="playlist_editor_dialog_neutral_button">刪除</string>
|
||||||
|
<string name="playlist_editor_dialog_positive_button">儲存</string>
|
||||||
|
<string name="playlist_editor_dialog_title">編輯播放清單</string>
|
||||||
|
<string name="playlist_page_play_button">播放</string>
|
||||||
|
<string name="playlist_page_shuffle_button">隨機播放</string>
|
||||||
|
<string name="playlist_song_count">播放清單 • %1$d 首歌曲</string>
|
||||||
|
<string name="podcast_bottom_sheet_add_to_queue">新增到序列</string>
|
||||||
|
<string name="podcast_bottom_sheet_delete">刪除</string>
|
||||||
|
<string name="podcast_bottom_sheet_download">下載</string>
|
||||||
|
<string name="podcast_bottom_sheet_go_to_channel">前往該頻道</string>
|
||||||
|
<string name="podcast_bottom_sheet_play_next">下一首播放</string>
|
||||||
|
<string name="podcast_bottom_sheet_remove">移除</string>
|
||||||
|
<string name="podcast_channel_catalogue_title">頻道</string>
|
||||||
|
<string name="podcast_channel_catalogue_title_expanded">瀏覽頻道</string>
|
||||||
|
<string name="podcast_channel_editor_dialog_hint_rss_url">RSS 網址</string>
|
||||||
|
<string name="podcast_channel_editor_dialog_title">播客頻道</string>
|
||||||
|
<string name="podcast_channel_not_supported_snackbar">此伺服器不支援播客。</string>
|
||||||
|
<string name="podcast_channel_page_title_description_section">描述</string>
|
||||||
|
<string name="podcast_channel_page_title_episode_section">劇集</string>
|
||||||
|
<string name="podcast_channel_page_title_no_episode_available">沒有可用的劇集</string>
|
||||||
|
<string name="podcast_episode_download_request_snackbar">您的請求已發送至伺服器</string>
|
||||||
|
<string name="podcast_info_empty_button">單擊以隱藏該部分\n重啟應用程式後生效</string>
|
||||||
|
<string name="podcast_info_empty_subtitle">新增頻道後,您將在此處找到它</string>
|
||||||
|
<string name="podcast_info_empty_title">未找到播客!</string>
|
||||||
|
<string name="podcast_release_date_duration_formatter">%1$s • %2$s</string>
|
||||||
|
<string name="radio_dialog_not_supported_snackbar">伺服器不支援網路電臺管理。</string>
|
||||||
|
<string name="radio_editor_dialog_added">已新增電臺</string>
|
||||||
|
<string name="radio_editor_dialog_hint_homepage_url">電臺首頁 URL</string>
|
||||||
|
<string name="radio_editor_dialog_hint_name">電臺名稱</string>
|
||||||
|
<string name="radio_editor_dialog_hint_stream_url">廣播流 URL</string>
|
||||||
|
<string name="radio_editor_dialog_negative_button">取消</string>
|
||||||
|
<string name="radio_editor_dialog_neutral_button">刪除</string>
|
||||||
|
<string name="radio_editor_dialog_positive_button">儲存</string>
|
||||||
|
<string name="radio_editor_dialog_title">網路廣播電臺</string>
|
||||||
|
<string name="radio_editor_dialog_updated">已更新電臺</string>
|
||||||
|
<string name="radio_station_info_empty_button">單擊以隱藏該部分\n重啟應用程式後生效</string>
|
||||||
|
<string name="radio_station_info_empty_subtitle">新增廣播電臺後,您可以在此處找到它</string>
|
||||||
|
<string name="radio_station_info_empty_title">沒有找到電臺!</string>
|
||||||
|
<string name="rating_dialog_negative_button">取消</string>
|
||||||
|
<string name="rating_dialog_positive_button">儲存</string>
|
||||||
|
<string name="rating_dialog_title">評分</string>
|
||||||
|
<string name="search_hint">搜尋標題、藝術家或專輯</string>
|
||||||
|
<string name="search_info_minimum_characters">輸入至少三個字符</string>
|
||||||
|
<string name="search_sort_summary">啟用後將按時間排序搜尋,關閉則按名稱排序。</string>
|
||||||
|
<string name="search_sort_title">按時間排序最近搜尋</string>
|
||||||
|
<string name="search_title_album">專輯</string>
|
||||||
|
<string name="search_title_artist">藝術家</string>
|
||||||
|
<string name="search_title_song">歌曲</string>
|
||||||
|
<string name="server_signup_dialog_action_delete_toast">長按刪除</string>
|
||||||
|
<string name="server_signup_dialog_action_low_security">低安全性</string>
|
||||||
|
<string name="server_signup_dialog_hint_local_address">本地 URL</string>
|
||||||
|
<string name="server_signup_dialog_hint_name">伺服器名稱</string>
|
||||||
|
<string name="server_signup_dialog_hint_password">密碼</string>
|
||||||
|
<string name="server_signup_dialog_hint_url">伺服器位址</string>
|
||||||
|
<string name="server_signup_dialog_hint_username">使用者名稱</string>
|
||||||
|
<string name="server_signup_dialog_negative_button">取消</string>
|
||||||
|
<string name="server_signup_dialog_neutral_button">刪除</string>
|
||||||
|
<string name="server_signup_dialog_positive_button">儲存</string>
|
||||||
|
<string name="server_signup_dialog_title">新增伺服器</string>
|
||||||
|
<string name="server_unreachable_dialog_negative_button">取消</string>
|
||||||
|
<string name="server_unreachable_dialog_neutral_button">前往登入</string>
|
||||||
|
<string name="server_unreachable_dialog_positive_button">仍然繼續</string>
|
||||||
|
<string name="server_unreachable_dialog_summary">請求的伺服器不可用。 如果您選擇繼續,此對話框在接下來的一個小時內將不會再次出現。</string>
|
||||||
|
<string name="server_unreachable_dialog_title">伺服器無法存取</string>
|
||||||
|
<string name="settings_about_summary">Tempus 是 Subsonic 的開源輕量級音樂客戶端,專為 Android 設計和構建。</string>
|
||||||
|
<string name="settings_about_title">關於</string>
|
||||||
|
<string name="settings_album_detail">顯示專輯詳情</string>
|
||||||
|
<string name="settings_album_detail_summary">啟用後將在專輯頁顯示流派、歌曲數量等資訊</string>
|
||||||
|
<string name="settings_allow_playlist_duplicates">允許新增重複歌曲到播放清單</string>
|
||||||
|
<string name="settings_allow_playlist_duplicates_summary">啟用後則新增到播放清單時將不再檢查重複內容。</string>
|
||||||
|
<string name="settings_always_on_display">保持螢幕常亮</string>
|
||||||
|
<string name="settings_app_equalizer">均衡器</string>
|
||||||
|
<string name="settings_app_equalizer_summary">開啟搭載均衡器</string>
|
||||||
|
<string name="settings_artist_sort_by_album_count">按專輯數量排序藝術家</string>
|
||||||
|
<string name="settings_artist_sort_by_album_count_summary">啟用後按專輯數量排序;關閉則按名稱排序。</string>
|
||||||
|
<string name="settings_audio_quality">顯示音訊品質</string>
|
||||||
|
<string name="settings_audio_quality_summary">顯示歌曲的位元率和音訊格式。</string>
|
||||||
|
<string name="settings_audio_transcode_download_format">轉碼格式</string>
|
||||||
|
<string name="settings_audio_transcode_download_priority_summary">啟用後 Tempus 將不會強制使用下面的轉碼設定下載歌曲。</string>
|
||||||
|
<string name="settings_audio_transcode_download_priority_title">優先考慮伺服器上用於流式傳輸的設定</string>
|
||||||
|
<string name="settings_audio_transcode_download_summary">啟用後 Tempus 將下載轉碼後的歌曲。</string>
|
||||||
|
<string name="settings_audio_transcode_download_title">下載轉碼後的歌曲</string>
|
||||||
|
<string name="settings_audio_transcode_estimate_content_length_summary">啟用後將發送請求到伺服器以查詢歌曲的大概持續時間。</string>
|
||||||
|
<string name="settings_audio_transcode_estimate_content_length_title">大概內容長度</string>
|
||||||
|
<string name="settings_audio_transcode_format_download">用於下載的轉碼格式</string>
|
||||||
|
<string name="settings_audio_transcode_format_mobile">行動資料下的轉碼格式</string>
|
||||||
|
<string name="settings_audio_transcode_format_wifi">Wi-Fi 下的轉碼格式</string>
|
||||||
|
<string name="settings_audio_transcode_priority_summary">啟用後 Tempus 將不會強制使用下面的轉碼設定流式傳輸歌曲。</string>
|
||||||
|
<string name="settings_audio_transcode_priority_title">優先考慮伺服器轉碼設定</string>
|
||||||
|
<string name="settings_audio_transcode_priority_toast">歌曲轉碼設定優先級設定為伺服器</string>
|
||||||
|
<string name="settings_auto_download_lyrics">自動下載歌詞</string>
|
||||||
|
<string name="settings_auto_download_lyrics_summary">自動儲存可用歌詞,以便離線時查看。</string>
|
||||||
|
<string name="settings_buffering_strategy">快取策略</string>
|
||||||
|
<string name="settings_buffering_strategy_summary">為了使更改生效,您必須手動重新啟動應用程式。</string>
|
||||||
|
<string name="settings_choose_download_folder">選擇一個音樂下載目錄</string>
|
||||||
|
<string name="settings_clear_download_folder">清空下載資料夾</string>
|
||||||
|
<string name="settings_continuous_play_summary">允許在播放清單結束後,播放相似的歌曲。</string>
|
||||||
|
<string name="settings_continuous_play_title">連續播放</string>
|
||||||
|
<string name="settings_covers_cache">圖片快取大小</string>
|
||||||
|
<string name="settings_data_saving_mode_summary">為了減少資料消耗,請避免下載封面。</string>
|
||||||
|
<string name="settings_data_saving_mode_title">限制行動資料使用</string>
|
||||||
|
<string name="settings_delete_download_storage_summary">繼續當前操作將導致所有已儲存的項目被永久刪除。</string>
|
||||||
|
<string name="settings_delete_download_storage_title">刪除已儲存的項目</string>
|
||||||
|
<string name="settings_download_folder_cleared">下載資料夾已清除。</string>
|
||||||
|
<string name="settings_download_folder_set">已設定下載資料夾</string>
|
||||||
|
<string name="settings_download_storage_title">下載儲存</string>
|
||||||
|
<string name="settings_github_link">https://github.com/eddyizm/tempus</string>
|
||||||
|
<string name="settings_github_summary">關注開發進展</string>
|
||||||
|
<string name="settings_github_title">Github</string>
|
||||||
|
<string name="settings_github_update">更新</string>
|
||||||
|
<string name="settings_github_update_summary">GitHub 版本預設會自動檢查 APK 更新。您可以關閉此開關以禁用自動檢查。</string>
|
||||||
|
<string name="settings_github_update_title">請存取 Github 以檢查更新</string>
|
||||||
|
<string name="settings_image_size">設定圖像解析度</string>
|
||||||
|
<string name="settings_item_rating">顯示評分</string>
|
||||||
|
<string name="settings_item_rating_summary">啟用後則顯示項目的評分和收藏狀態。</string>
|
||||||
|
<string name="settings_language">語言</string>
|
||||||
|
<string name="settings_logout_title">註銷登入</string>
|
||||||
|
<string name="settings_max_bitrate_download">用於下載的位元率</string>
|
||||||
|
<string name="settings_max_bitrate_mobile">行動資料下的位元率</string>
|
||||||
|
<string name="settings_max_bitrate_wifi">Wi-Fi 下的位元率</string>
|
||||||
|
<string name="settings_media_cache">媒體檔案快取大小</string>
|
||||||
|
<string name="settings_music_directory">顯示音樂目錄</string>
|
||||||
|
<string name="settings_music_directory_summary">啟用後則顯示音樂目錄部分。 請注意,要使資料夾導航正常工作,伺服器必須支援此功能。</string>
|
||||||
|
<string name="settings_podcast">顯示播客</string>
|
||||||
|
<string name="settings_podcast_summary">啟用後則顯示播客部分。</string>
|
||||||
|
<string name="settings_queue_syncing_countdown">同步定時器</string>
|
||||||
|
<string name="settings_queue_syncing_summary">啟用後將允許當前使用者儲存其播放序列,並能夠在開啟應用程式時載入儲存狀態。</string>
|
||||||
|
<string name="settings_queue_syncing_title">同步當前使用者的播放序列</string>
|
||||||
|
<string name="settings_radio">顯示電臺</string>
|
||||||
|
<string name="settings_radio_summary">啟用後,則顯示電臺部分。</string>
|
||||||
|
<string name="settings_replay_gain">設定播放增益模式</string>
|
||||||
|
<string name="settings_rounded_corner">圓角</string>
|
||||||
|
<string name="settings_rounded_corner_size">圓角大小</string>
|
||||||
|
<string name="settings_rounded_corner_size_summary">設定圓角的大小。</string>
|
||||||
|
<string name="settings_rounded_corner_summary">啟用後則為所有渲染的封面設定圓角。更改將在應用程式重新啟動後生效。</string>
|
||||||
|
<string name="settings_scan_result">正在掃描:已發現 %1$d 首歌曲</string>
|
||||||
|
<string name="settings_scan_title">掃描曲庫</string>
|
||||||
|
<string name="settings_scrobble_title">啟用音樂記錄</string>
|
||||||
|
<string name="settings_set_download_folder">設定下載資料夾</string>
|
||||||
|
<string name="settings_share_title">啟用音樂共享</string>
|
||||||
|
<string name="settings_show_mini_shuffle_button">顯示隨機按鈕</string>
|
||||||
|
<string name="settings_show_mini_shuffle_button_summary">啟用後,在迷你播放器中顯示隨機播放按鈕,並移除收藏按鈕。</string>
|
||||||
|
<string name="settings_song_rating">顯示歌曲評分</string>
|
||||||
|
<string name="settings_song_rating_summary">啟用後歌曲詳情頁將顯示五星評分。\n\n*需重啟應用程式後生效</string>
|
||||||
|
<string name="settings_streaming_cache_size">播放快取大小</string>
|
||||||
|
<string name="settings_streaming_cache_storage_title">快取目錄設定</string>
|
||||||
|
<string name="settings_sub_summary_scrobble">請注意,音樂記錄同時也依賴於伺服器是否能夠接收這些資料。</string>
|
||||||
|
<string name="settings_summary_replay_gain">播放增益(Replay gain)允許您通過調整音軌的音量,以獲得始終如一的聆聽體驗。 僅當歌曲標籤包含必要的元資料時,此設定才有效。</string>
|
||||||
|
<string name="settings_summary_scrobble">音樂記錄(Scrobbling)允許您的設備將您收聽的歌曲的相關資訊發送到音樂伺服器。 這些資訊有助於基於您的音樂偏好生成個性化推薦。</string>
|
||||||
|
<string name="settings_summary_share">允許使用者通過連結共享音樂。 該功能需要伺服器端支援並啟用,並且僅限於單首歌曲、專輯和序列。</string>
|
||||||
|
<string name="settings_summary_skip_min_star_rating">收聽電臺,即時混合和隨機播放時,低於特定評分的歌曲將會被忽略。</string>
|
||||||
|
<string name="settings_summary_streaming_cache_size">%1$s \n已使用: %2$s MiB</string>
|
||||||
|
<string name="settings_summary_syncing">返回當前使用者的播放序列狀態。 這包括播放序列中的歌曲、正在播放的歌曲以及歌曲播放進度。需要伺服器支援此功能。</string>
|
||||||
|
<string name="settings_summary_transcoding">轉碼模式優先級設定。 如果設定為「播放原始」,檔案的位元率將不會更改。</string>
|
||||||
|
<string name="settings_summary_transcoding_download">下載轉碼後的媒體。 啟用後將不會下載原始資料,而是使用以下設定。\n如果「用於下載的轉碼格式」設定為「下載原始」,則檔案的位元率不會更改。</string>
|
||||||
|
<string name="settings_summary_transcoding_estimate_content_length">當檔案即時轉碼時,客戶端通常不會顯示歌曲長度。 可以向支援該功能的伺服器發送請求,大概正在播放的歌曲的持續時間,但可能回應變慢。</string>
|
||||||
|
<string name="settings_support_discussion_link">https://github.com/eddyizm/tempus/discussions</string>
|
||||||
|
<string name="settings_support_summary">加入社群討論並取得幫助</string>
|
||||||
|
<string name="settings_support_title">使用者支援</string>
|
||||||
|
<string name="settings_sync_starred_albums_for_offline_use_summary">啟用後將下載收藏的專輯以供離線使用。</string>
|
||||||
|
<string name="settings_sync_starred_albums_for_offline_use_title">下載收藏的專輯以供離線使用</string>
|
||||||
|
<string name="settings_sync_starred_artists_for_offline_use_summary">啟用後將自動下載收藏的藝術家以供離線使用。</string>
|
||||||
|
<string name="settings_sync_starred_artists_for_offline_use_title">同步收藏的藝術家以供離線使用</string>
|
||||||
|
<string name="settings_sync_starred_tracks_for_offline_use_summary">啟用後將下載收藏的歌曲以供離線使用。</string>
|
||||||
|
<string name="settings_sync_starred_tracks_for_offline_use_title">同步收藏的歌曲以供離線使用</string>
|
||||||
|
<string name="settings_system_equalizer_summary">調整音訊設定</string>
|
||||||
|
<string name="settings_system_equalizer_title">系統均衡器</string>
|
||||||
|
<string name="settings_system_language">系統語言</string>
|
||||||
|
<string name="settings_theme">主題</string>
|
||||||
|
<string name="settings_title_data">資料</string>
|
||||||
|
<string name="settings_title_general">通用</string>
|
||||||
|
<string name="settings_title_playlist">播放清單</string>
|
||||||
|
<string name="settings_title_rating">評分</string>
|
||||||
|
<string name="settings_title_replay_gain">播放增益</string>
|
||||||
|
<string name="settings_title_scrobble">音樂記錄</string>
|
||||||
|
<string name="settings_title_share">分享</string>
|
||||||
|
<string name="settings_title_skip_min_star_rating">根據評分忽略歌曲</string>
|
||||||
|
<string name="settings_title_skip_min_star_rating_dialog">根據歌曲評分篩選:</string>
|
||||||
|
<string name="settings_title_syncing">同步</string>
|
||||||
|
<string name="settings_title_transcoding">轉碼</string>
|
||||||
|
<string name="settings_title_transcoding_download">轉碼下載</string>
|
||||||
|
<string name="settings_title_ui">界面</string>
|
||||||
|
<string name="settings_transcoded_download">轉碼下載</string>
|
||||||
|
<string name="settings_version_summary" translatable="false">3.1.0</string>
|
||||||
|
<string name="settings_version_title">版本</string>
|
||||||
|
<string name="settings_wifi_only_summary">在通過行動網路進行流式傳輸之前請求使用者確認。</string>
|
||||||
|
<string name="settings_wifi_only_title">提示僅通過 Wi-Fi 進行流式傳輸</string>
|
||||||
|
<string name="share_bottom_sheet_copy_link">複製連結</string>
|
||||||
|
<string name="share_bottom_sheet_delete">刪除分享</string>
|
||||||
|
<string name="share_bottom_sheet_update">更新分享</string>
|
||||||
|
<string name="share_no_expiration">永不過期</string>
|
||||||
|
<string name="share_subtitle_item">到期日期:%1$s</string>
|
||||||
|
<string name="share_unsupported_error">不支援分享或未啟用</string>
|
||||||
|
<string name="share_update_dialog_hint_description">描述</string>
|
||||||
|
<string name="share_update_dialog_hint_expiration_date">截止日期</string>
|
||||||
|
<string name="share_update_dialog_negative_button">取消</string>
|
||||||
|
<string name="share_update_dialog_positive_button">儲存</string>
|
||||||
|
<string name="share_update_dialog_title">分享</string>
|
||||||
|
<string name="song_bottom_sheet_add_to_playlist">新增到播放清單</string>
|
||||||
|
<string name="song_bottom_sheet_add_to_queue">新增到序列</string>
|
||||||
|
<string name="song_bottom_sheet_download">下載</string>
|
||||||
|
<string name="song_bottom_sheet_error_retrieving_album">檢索相簿時出錯</string>
|
||||||
|
<string name="song_bottom_sheet_error_retrieving_artist">檢索藝術家時出錯</string>
|
||||||
|
<string name="song_bottom_sheet_go_to_album">前往該專輯</string>
|
||||||
|
<string name="song_bottom_sheet_go_to_artist">前往該藝術家</string>
|
||||||
|
<string name="song_bottom_sheet_instant_mix">即時混合</string>
|
||||||
|
<string name="song_bottom_sheet_play_next">下一首播放</string>
|
||||||
|
<string name="song_bottom_sheet_rate">評分</string>
|
||||||
|
<string name="song_bottom_sheet_remove">移除</string>
|
||||||
|
<string name="song_bottom_sheet_share">分享</string>
|
||||||
|
<string name="song_list_page_downloaded">已下載</string>
|
||||||
|
<string name="song_list_page_most_played">最常播放的歌曲</string>
|
||||||
|
<string name="song_list_page_recently_added">最近新增的歌曲</string>
|
||||||
|
<string name="song_list_page_recently_played">最近播放的歌曲</string>
|
||||||
|
<string name="song_list_page_starred">已收藏的歌曲</string>
|
||||||
|
<string name="song_list_page_top">%1$s 的熱門歌曲</string>
|
||||||
|
<string name="song_list_page_year">年份 %1$d</string>
|
||||||
|
<string name="song_subtitle_formatter">%1$s • %2$s %3$s</string>
|
||||||
|
<plurals name="songs_download_started">
|
||||||
|
<item quantity="one">正在下載 %d 首歌曲</item>
|
||||||
|
<item quantity="other">正在下載 %d 首歌曲</item>
|
||||||
|
</plurals>
|
||||||
|
<string name="starred_album_sync_dialog_summary">下載收藏的專輯可能會消耗大量行動資料流量。</string>
|
||||||
|
<string name="starred_album_sync_dialog_title">同步收藏的專輯</string>
|
||||||
|
<string name="starred_artist_sync_dialog_summary">下載收藏的藝術家可能會消耗大量行動資料流量。</string>
|
||||||
|
<string name="starred_artist_sync_dialog_title">同步收藏的藝術家</string>
|
||||||
|
<string name="starred_sync_dialog_negative_button">取消</string>
|
||||||
|
<string name="starred_sync_dialog_neutral_button">繼續</string>
|
||||||
|
<string name="starred_sync_dialog_positive_button">繼續並下載</string>
|
||||||
|
<string name="starred_sync_dialog_summary">下載收藏的歌曲可能會消耗大量行動資料流量。</string>
|
||||||
|
<string name="starred_sync_dialog_title">同步收藏的歌曲</string>
|
||||||
|
<string name="streaming_cache_storage_dialog_sub_summary">要使更改生效,請重新啟動應用程式。</string>
|
||||||
|
<string name="streaming_cache_storage_dialog_summary">切換快取檔案的儲存路徑可能會導致原位置儲存的快取檔案被清空。</string>
|
||||||
|
<string name="streaming_cache_storage_dialog_title">選擇儲存位置</string>
|
||||||
|
<string name="streaming_cache_storage_external_dialog_positive_button">外部</string>
|
||||||
|
<string name="streaming_cache_storage_internal_dialog_negative_button">內部</string>
|
||||||
|
<string name="support_url">https://ko-fi.com/eddyizm</string>
|
||||||
|
<string name="track_info_album">專輯</string>
|
||||||
|
<string name="track_info_artist">藝術家</string>
|
||||||
|
<string name="track_info_bit_depth">位深</string>
|
||||||
|
<string name="track_info_bitrate">位元率</string>
|
||||||
|
<string name="track_info_content_type">內容類型</string>
|
||||||
|
<string name="track_info_dialog_positive_button">確定</string>
|
||||||
|
<string name="track_info_dialog_title">歌曲資訊</string>
|
||||||
|
<string name="track_info_disc_number">碟片編號</string>
|
||||||
|
<string name="track_info_duration">持續時間</string>
|
||||||
|
<string name="track_info_genre">流派</string>
|
||||||
|
<string name="track_info_path">路徑</string>
|
||||||
|
<string name="track_info_sampling_rate">採樣率</string>
|
||||||
|
<string name="track_info_size">大小</string>
|
||||||
|
<string name="track_info_suffix">後綴</string>
|
||||||
|
<string name="track_info_summary_downloaded_file">該檔案已使用 Subsonic API 下載。 檔案的編碼和位元率與原始檔一致。</string>
|
||||||
|
<string name="track_info_summary_full_transcode">本應用程式將請求伺服器對檔案進行轉碼並修改其位元率。 使用者請求的編解碼器是%1$s,位元率為%2$s。 對所選格式的檔案的編碼和位元率的任何潛在更改都將由伺服器處理,伺服器可能支援也可能不支援該操作。</string>
|
||||||
|
<string name="track_info_summary_original_file">本應用程式只會讀取伺服器提供的原始檔案。 本應用程式將明確向伺服器請求具有原始源位元率的未轉碼檔案。</string>
|
||||||
|
<string name="track_info_summary_server_prioritized">要播放的檔案品質取決於伺服器設定。 本應用程式不會強制選擇任何用於潛在轉碼的編碼和位元率。</string>
|
||||||
|
<string name="track_info_summary_transcoding_bitrate">本應用程式將請求伺服器修改檔案的位元率。 使用者請求的位元率為%1$s,而原始檔的編碼將保持不變。 對所選格式的檔案位元率的任何更改都將由伺服器完成,伺服器可能支援也可能不支援該操作。</string>
|
||||||
|
<string name="track_info_summary_transcoding_codec">本應用程式將請求伺服器對檔案進行轉碼。 使用者請求的編解碼器是%1$s,而位元率將與原始檔相同。 將檔案轉碼為所選格式的可能性取決於伺服器,因為它可能支援也可能不支援該操作。</string>
|
||||||
|
<string name="track_info_title">標題</string>
|
||||||
|
<string name="track_info_track_number">歌曲編號</string>
|
||||||
|
<string name="track_info_transcoded_content_type">轉碼內容類型</string>
|
||||||
|
<string name="track_info_transcoded_suffix">轉碼後綴</string>
|
||||||
|
<string name="track_info_year">年份</string>
|
||||||
|
<string name="undraw_page">unDraw</string>
|
||||||
|
<string name="undraw_thanks">特別感謝 unDraw,沒有它提供的插圖,我們的應用程式不可能會如此精美。</string>
|
||||||
|
<string name="undraw_url">https://undraw.co/</string>
|
||||||
|
<string name="widget_content_desc_album_art">專輯封面</string>
|
||||||
|
<string name="widget_content_desc_next">下一首</string>
|
||||||
|
<string name="widget_content_desc_play_pause">播放或暫停</string>
|
||||||
|
<string name="widget_content_desc_prev">上一首</string>
|
||||||
|
<string name="widget_content_desc_repeat">更改循環模式</string>
|
||||||
|
<string name="widget_content_desc_shuffle">切換隨機播放</string>
|
||||||
|
<string name="widget_label">Tempus 小組件</string>
|
||||||
|
<string name="widget_not_playing">未播放</string>
|
||||||
|
<string name="widget_placeholder_subtitle">開啟 Tempus</string>
|
||||||
|
<string name="widget_time_duration_placeholder">0:00</string>
|
||||||
|
<string name="widget_time_elapsed_placeholder">0:00</string>
|
||||||
|
</resources>
|
||||||
@@ -279,6 +279,20 @@
|
|||||||
<item>7</item>
|
<item>7</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="tile_size_titles">
|
||||||
|
<item>Tiny</item>
|
||||||
|
<item>Small</item>
|
||||||
|
<item>Medium</item>
|
||||||
|
<item>Large</item>
|
||||||
|
<item>Default</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="tile_size_divisor">
|
||||||
|
<item>6</item>
|
||||||
|
<item>5</item>
|
||||||
|
<item>4</item>
|
||||||
|
<item>3</item>
|
||||||
|
<item>2</item>
|
||||||
|
</string-array>
|
||||||
<!-- Add by MFO -->
|
<!-- Add by MFO -->
|
||||||
<string-array name="aa_tab_titles">
|
<string-array name="aa_tab_titles">
|
||||||
<item>Do not display</item>
|
<item>Do not display</item>
|
||||||
@@ -296,8 +310,9 @@
|
|||||||
<!-- <item>For you</item> -->
|
<!-- <item>For you</item> -->
|
||||||
<item>Star tracks</item>
|
<item>Star tracks</item>
|
||||||
<item>Star albums</item>
|
<item>Star albums</item>
|
||||||
<item>Star artistes</item>
|
<item>Star artists</item>
|
||||||
<item>Random</item>
|
<item>Random</item>
|
||||||
|
<item>Genres</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="aa_tab_values">
|
<string-array name="aa_tab_values">
|
||||||
<item>-1</item>
|
<item>-1</item>
|
||||||
@@ -317,6 +332,7 @@
|
|||||||
<item>13</item>
|
<item>13</item>
|
||||||
<item>14</item>
|
<item>14</item>
|
||||||
<item>15</item>
|
<item>15</item>
|
||||||
|
<item>16</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<!-- end Add by MFO -->
|
<!-- end Add by MFO -->
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<color name="ic_launcher_background">#626A75</color>
|
|
||||||
</resources>
|
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
<string name="aa_podcast">Podcast</string>
|
<string name="aa_podcast">Podcast</string>
|
||||||
<string name="aa_radio">Radio</string>
|
<string name="aa_radio">Radio</string>
|
||||||
<string name="aa_random">Random</string>
|
<string name="aa_random">Random</string>
|
||||||
|
<string name="aa_genres">Genres</string>
|
||||||
<string name="aa_recent_albums">Recent</string>
|
<string name="aa_recent_albums">Recent</string>
|
||||||
<string name="aa_song_recently_played">Song played</string>
|
<string name="aa_song_recently_played">Song played</string>
|
||||||
<string name="aa_starred_albums">★ Albums</string>
|
<string name="aa_starred_albums">★ Albums</string>
|
||||||
@@ -402,6 +403,8 @@
|
|||||||
<string name="settings_androidauto_second_tab">Second tab display</string>
|
<string name="settings_androidauto_second_tab">Second tab display</string>
|
||||||
<string name="settings_androidauto_third_tab">Third tab display</string>
|
<string name="settings_androidauto_third_tab">Third tab display</string>
|
||||||
<string name="settings_androidauto_fourth_tab">Fourth tab display</string>
|
<string name="settings_androidauto_fourth_tab">Fourth tab display</string>
|
||||||
|
<string name="settings_androidauto_shuffle_genre_songs">Shuffle genre songs</string>
|
||||||
|
<string name="settings_androidauto_shuffle_genre_songs_summary">Play random songs when selecting a genre</string>
|
||||||
<string name="settings_audio_quality">Show audio quality</string>
|
<string name="settings_audio_quality">Show audio quality</string>
|
||||||
<string name="settings_audio_quality_summary">The bitrate and audio format will be shown for each audio track.</string>
|
<string name="settings_audio_quality_summary">The bitrate and audio format will be shown for each audio track.</string>
|
||||||
<string name="settings_song_rating">Show song star rating</string>
|
<string name="settings_song_rating">Show song star rating</string>
|
||||||
@@ -415,8 +418,8 @@
|
|||||||
<string name="settings_show_mini_shuffle_button_summary">If enabled, show the shuffle button, remove the heart in the mini player</string>
|
<string name="settings_show_mini_shuffle_button_summary">If enabled, show the shuffle button, remove the heart in the mini player</string>
|
||||||
<string name="settings_radio">Show radio</string>
|
<string name="settings_radio">Show radio</string>
|
||||||
<string name="settings_radio_summary">If enabled, show the radio section. Restart the app for it to take full effect.</string>
|
<string name="settings_radio_summary">If enabled, show the radio section. Restart the app for it to take full effect.</string>
|
||||||
<string name="settings_enable_drawer_on_landscape">Enable drawer on portrait [Experimental]</string>
|
<string name="settings_enable_drawer_on_landscape">Enable drawer on portrait</string>
|
||||||
<string name="settings_enable_drawer_on_landscape_summary">Unlocks the lateral landscape menu drawer on portrait. The changes will take effect on restart.</string>
|
<string name="settings_enable_drawer_on_landscape_summary">Unlocks the lateral landscape menu drawer on portrait.</string>
|
||||||
<string name="settings_hide_bottom_navbar_on_portrait">Hide bottom navbar on portrait [Experimental]</string>
|
<string name="settings_hide_bottom_navbar_on_portrait">Hide bottom navbar on portrait [Experimental]</string>
|
||||||
<string name="settings_hide_bottom_navbar_on_portrait_summary">Experimental.Increases vertical space by removing the bottom navbar. The changes will take effect on restart.</string>
|
<string name="settings_hide_bottom_navbar_on_portrait_summary">Experimental.Increases vertical space by removing the bottom navbar. The changes will take effect on restart.</string>
|
||||||
<string name="settings_auto_download_lyrics">Auto download lyrics</string>
|
<string name="settings_auto_download_lyrics">Auto download lyrics</string>
|
||||||
@@ -450,6 +453,7 @@
|
|||||||
<string name="settings_sync_starred_tracks_for_offline_use_summary">If enabled, starred tracks will be downloaded for offline use.</string>
|
<string name="settings_sync_starred_tracks_for_offline_use_summary">If enabled, starred tracks will be downloaded for offline use.</string>
|
||||||
<string name="settings_sync_starred_tracks_for_offline_use_title">Sync starred tracks for offline use</string>
|
<string name="settings_sync_starred_tracks_for_offline_use_title">Sync starred tracks for offline use</string>
|
||||||
<string name="settings_theme">Theme</string>
|
<string name="settings_theme">Theme</string>
|
||||||
|
<string name="settings_tile_size">Tiles size</string>
|
||||||
<string name="settings_title_data">Data</string>
|
<string name="settings_title_data">Data</string>
|
||||||
<string name="settings_title_general">General</string>
|
<string name="settings_title_general">General</string>
|
||||||
<string name="settings_title_playlist">Playlist</string>
|
<string name="settings_title_playlist">Playlist</string>
|
||||||
@@ -603,4 +607,7 @@
|
|||||||
|
|
||||||
<string name="search_sort_title">Sort recent searches chronologically</string>
|
<string name="search_sort_title">Sort recent searches chronologically</string>
|
||||||
<string name="search_sort_summary">If enabled, sort searches chronologically. Sort by name if disabled.</string>
|
<string name="search_sort_summary">If enabled, sort searches chronologically. Sort by name if disabled.</string>
|
||||||
|
<string name="search_all_songs_loading">Getting all songs ...</string>
|
||||||
|
<string name="search_all_songs">all %1$s songs</string>
|
||||||
|
<string name="search_all_songs_play">Play %1$s</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -54,6 +54,15 @@
|
|||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="always_on_display" />
|
android:key="always_on_display" />
|
||||||
|
|
||||||
|
<ListPreference
|
||||||
|
app:defaultValue="2"
|
||||||
|
app:dialogTitle="@string/settings_tile_size"
|
||||||
|
app:entries="@array/tile_size_titles"
|
||||||
|
app:entryValues="@array/tile_size_divisor"
|
||||||
|
app:key="tile_size"
|
||||||
|
app:title="@string/settings_tile_size"
|
||||||
|
app:useSimpleSummaryProvider="true" />
|
||||||
|
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:title="@string/settings_enable_drawer_on_landscape"
|
android:title="@string/settings_enable_drawer_on_landscape"
|
||||||
android:key="enable_drawer_on_portrait"
|
android:key="enable_drawer_on_portrait"
|
||||||
@@ -147,15 +156,6 @@
|
|||||||
android:summary="@string/search_sort_summary"
|
android:summary="@string/search_sort_summary"
|
||||||
android:key="sort_search_chronologically" />
|
android:key="sort_search_chronologically" />
|
||||||
|
|
||||||
<ListPreference
|
|
||||||
app:defaultValue="4"
|
|
||||||
app:dialogTitle="@string/settings_title_ui_landscape_items_per_row_dialog"
|
|
||||||
app:entries="@array/landscape_items_per_row"
|
|
||||||
app:entryValues="@array/landscape_items_per_row_values"
|
|
||||||
app:key="landscape_items_per_row"
|
|
||||||
android:summary="@string/settings_summary_landscape_items_per_row"
|
|
||||||
app:title="@string/settings_title_ui_landscape_items_per_row" />
|
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
<PreferenceCategory app:title="@string/settings_title_playlist">
|
<PreferenceCategory app:title="@string/settings_title_playlist">
|
||||||
@@ -521,6 +521,11 @@
|
|||||||
app:title="@string/settings_androidauto_fourth_tab"
|
app:title="@string/settings_androidauto_fourth_tab"
|
||||||
app:useSimpleSummaryProvider="true" />
|
app:useSimpleSummaryProvider="true" />
|
||||||
|
|
||||||
|
<SwitchPreference
|
||||||
|
android:title="@string/settings_androidauto_shuffle_genre_songs"
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="androidauto_shuffle_genre_songs" />
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
<!-- end Add by MFO -->
|
<!-- end Add by MFO -->
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
<locale android:name="de-DE"/> <!-- German -->
|
<locale android:name="de-DE"/> <!-- German -->
|
||||||
<locale android:name="fr-FR"/> <!-- French -->
|
<locale android:name="fr-FR"/> <!-- French -->
|
||||||
<locale android:name="zh-CN"/> <!-- Simplified Chinese-->
|
<locale android:name="zh-CN"/> <!-- Simplified Chinese-->
|
||||||
|
<locale android:name="zh-TW"/> <!-- Traditional Chinese-->
|
||||||
<locale android:name="ko-KR"/> <!-- Korean-->
|
<locale android:name="ko-KR"/> <!-- Korean-->
|
||||||
<locale android:name="pt-BR"/> <!-- Brazilian Portuguese -->
|
<locale android:name="pt-BR"/> <!-- Brazilian Portuguese -->
|
||||||
<locale android:name="it-IT"/> <!-- Italian -->
|
<locale android:name="it-IT"/> <!-- Italian -->
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ object MediaBrowserTree {
|
|||||||
private const val STARRED_ARTISTS_ID = "[starredArtistsID]"
|
private const val STARRED_ARTISTS_ID = "[starredArtistsID]"
|
||||||
private const val RANDOM_ID = "[randomID]"
|
private const val RANDOM_ID = "[randomID]"
|
||||||
private const val FOLDER_ID = "[folderID]"
|
private const val FOLDER_ID = "[folderID]"
|
||||||
|
private const val GENRES_ID = "[genresID]"
|
||||||
|
|
||||||
// System functions
|
// System functions
|
||||||
private const val INDEX_ID = "[indexID]"
|
private const val INDEX_ID = "[indexID]"
|
||||||
@@ -178,7 +179,8 @@ object MediaBrowserTree {
|
|||||||
STARRED_TRACKS_ID,
|
STARRED_TRACKS_ID,
|
||||||
STARRED_ALBUMS_ID,
|
STARRED_ALBUMS_ID,
|
||||||
STARRED_ARTISTS_ID,
|
STARRED_ARTISTS_ID,
|
||||||
RANDOM_ID
|
RANDOM_ID,
|
||||||
|
GENRES_ID
|
||||||
)
|
)
|
||||||
|
|
||||||
// Root level
|
// Root level
|
||||||
@@ -419,6 +421,19 @@ object MediaBrowserTree {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
treeNodes[GENRES_ID] =
|
||||||
|
MediaItemNode(
|
||||||
|
buildMediaItem(
|
||||||
|
gridView = albumView,
|
||||||
|
title = appContext.getString(R.string.aa_genres),
|
||||||
|
mediaId = GENRES_ID,
|
||||||
|
isPlayable = false,
|
||||||
|
isBrowsable = true,
|
||||||
|
imageUri = iconUri(R.drawable.ic_aa_genres),
|
||||||
|
mediaType = MediaMetadata.MEDIA_TYPE_FOLDER_MIXED
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
val root = treeNodes[ROOT_ID]!!
|
val root = treeNodes[ROOT_ID]!!
|
||||||
val selectedIds = mutableSetOf<String>()
|
val selectedIds = mutableSetOf<String>()
|
||||||
|
|
||||||
@@ -474,6 +489,7 @@ object MediaBrowserTree {
|
|||||||
STARRED_ALBUMS_ID -> automotiveRepository.getStarredAlbums(id)
|
STARRED_ALBUMS_ID -> automotiveRepository.getStarredAlbums(id)
|
||||||
STARRED_ARTISTS_ID -> automotiveRepository.getStarredArtists(id)
|
STARRED_ARTISTS_ID -> automotiveRepository.getStarredArtists(id)
|
||||||
RANDOM_ID -> automotiveRepository.getRandomSongs(100)
|
RANDOM_ID -> automotiveRepository.getRandomSongs(100)
|
||||||
|
GENRES_ID -> automotiveRepository.getGenres(id)
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
if (id.startsWith(LAST_PLAYED_ID)) {
|
if (id.startsWith(LAST_PLAYED_ID)) {
|
||||||
@@ -512,6 +528,13 @@ object MediaBrowserTree {
|
|||||||
return automotiveRepository.getArtistAlbum(STARRED_ALBUMS_ID,id.removePrefix(STARRED_ARTISTS_ID))
|
return automotiveRepository.getArtistAlbum(STARRED_ALBUMS_ID,id.removePrefix(STARRED_ARTISTS_ID))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (id.startsWith(GENRES_ID)) {
|
||||||
|
val shuffle = Preferences.isAndroidAutoShuffleGenreSongsEnabled()
|
||||||
|
// If the user doesn't want random songs, it's likely it's for perusing them, so provide as many as possible
|
||||||
|
val count = if (shuffle) 100 else 500
|
||||||
|
return automotiveRepository.getSongsByGenre(id.removePrefix(GENRES_ID), count, shuffle)
|
||||||
|
}
|
||||||
|
|
||||||
if (id.startsWith(PLAYLIST_ID)) {
|
if (id.startsWith(PLAYLIST_ID)) {
|
||||||
return automotiveRepository.getPlaylistSongs(id.removePrefix(PLAYLIST_ID))
|
return automotiveRepository.getPlaylistSongs(id.removePrefix(PLAYLIST_ID))
|
||||||
}
|
}
|
||||||
|
|||||||
10
fastlane/metadata/android/en-US/changelogs/24.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
* chore(i18n): Improve Russian translation
|
||||||
|
* feat: tile size manager
|
||||||
|
* chore(i18n): Translated to zh_TW
|
||||||
|
* fix: Show full album name when displaying details
|
||||||
|
* chore(i18n): Update Spanish translation
|
||||||
|
* fix: Relocate "Offline mode" text
|
||||||
|
* chore(i18n): Update Polish translation
|
||||||
|
* refactor: navigation and bottom sheet
|
||||||
|
* feat: new Logo icon/adaptive icon update/refresh
|
||||||
|
* feat: Added all-songs feature
|
||||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 137 KiB After Width: | Height: | Size: 157 KiB |