mirror of
https://github.com/antebudimir/tempus.git
synced 2025-12-31 09:33:33 +00:00
Merge pull request #28 from eddyizm/development
v3.11.2 - merging to main
This commit is contained in:
commit
e891214831
23 changed files with 1335 additions and 41 deletions
41
CHANGELOG.md
Normal file
41
CHANGELOG.md
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# Changelog
|
||||
|
||||
***This log is for this fork to detail updates since 3.9.0 from the main repo.***
|
||||
|
||||
## [3.11.2](https://github.com/eddyizm/tempo/releases/tag/v3.11.2) (2025-08-09)
|
||||
|
||||
|
||||
([Full Changelog](https://github.com/eddyizm/tempo/compare/v3.10.0...eddyizm:tempo:v3.11.2?expand=1))
|
||||
|
||||
**Housekeeping:**
|
||||
|
||||
- [Chore] Added change log.
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- [Fix] make hardcoded strings in home fragment dynamic [\#27](https://github.com/eddyizm/tempo/pull/22) ([jaime-grj](https://github.com/jaime-grj))
|
||||
|
||||
- [Fix] show "System default" language option, sort languages alphabetically, include country when showing language in settings [\#26](https://github.com/eddyizm/tempo/pull/26) ([jaime-grj ](https://github.com/jaime-grj))
|
||||
|
||||
- [Fix] check for IP connectivity instead of Internet access [\#25](https://github.com/eddyizm/tempo/pull/25) ([jaime-grj](https://github.com/jaime-grj))
|
||||
|
||||
- [Fix] hide unnecessary TextViews in AlbumPageFragment when there is no data, fixed incorrect album release date [\#24](https://github.com/eddyizm/tempo/pull/24) ([jaime-grj](https://github.com/jaime-grj))
|
||||
|
||||
- [Feat] show sampling rate and bit depth if available [\#22](https://github.com/eddyizm/tempo/pull/22) ([jaime-grj](https://github.com/jaime-grj))
|
||||
|
||||
- [Feat] Fix lyric scrolling during playback, keep screen on while viewing [\#20](https://github.com/eddyizm/tempo/pull/20) ([le-firehawk](https://github.com/le-firehawk))
|
||||
|
||||
## [3.10.0](https://github.com/eddyizm/tempo/releases/tag/v3.10.0) (2025-08-04)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- [Fix] redirection to artist fragment on artist label click [\#379](https://github.com/CappielloAntonio/tempo/pull/379)
|
||||
- [Fix] Player queue lag, limits [\#385](https://github.com/CappielloAntonio/tempo/pull/385)
|
||||
- [Fix] crash when sorting albums with a null artist [\#389](https://github.com/CappielloAntonio/tempo/pull/389)
|
||||
- [Feat] Display toast message after adding a song to a playlist [\#371](https://github.com/CappielloAntonio/tempo/pull/371)
|
||||
- [Feat] Album add to playlist context menu item [\#367](https://github.com/CappielloAntonio/tempo/pull/367)
|
||||
- [Feat] Store and retrieve replay and shuffle states in preferences [\#397](https://github.com/CappielloAntonio/tempo/pull/397)
|
||||
- [Feat] Enhance Android media player notification window #400
|
||||
[\#400](https://github.com/CappielloAntonio/tempo/pull/400)
|
||||
- [Chore] Spanish translation [\#374](https://github.com/CappielloAntonio/tempo/pull/374)
|
||||
- [Chore] Polish translation [\#378](https://github.com/CappielloAntonio/tempo/pull/378)
|
||||
11
README.md
11
README.md
|
|
@ -26,16 +26,7 @@ Tempo does not rely on magic algorithms to decide what you should listen to. Ins
|
|||
|
||||
This fork is my attempt to keep development moving forward and merge in PR's that have been sitting for a while in the main repo. Thankful to @CappielloAntonio for the amazing app and hopefully we can continue to build on top of it. I will only be releasing on github and if I am not able to merge back to the main repo, I plan to rename the app to be able to publish it to fdroid and possibly google play? We will see.
|
||||
|
||||
[v3.10.0](https://github.com/eddyizm/tempo/releases/tag/v3.10.0) applies the following PR's (fix/feat/chore):
|
||||
fix: [379](https://github.com/CappielloAntonio/tempo/pull/379) -Fix: redirection to artist fragment on artist label click
|
||||
fix: [385](https://github.com/CappielloAntonio/tempo/pull/385) -Player queue lag, limits
|
||||
fix: [389](https://github.com/CappielloAntonio/tempo/pull/389) -Fix crash when sorting albums with a null artist
|
||||
feat: [371](https://github.com/CappielloAntonio/tempo/pull/371) -Display toast message after adding a song to a playlist
|
||||
feat: [367](https://github.com/CappielloAntonio/tempo/pull/367) -Album add to playlist context menu item
|
||||
chore: [374](https://github.com/CappielloAntonio/tempo/pull/374) -Spanish translation
|
||||
feat: [397](https://github.com/CappielloAntonio/tempo/pull/397) -Store and retrieve replay and shuffle states in preferences
|
||||
feat:[400](https://github.com/CappielloAntonio/tempo/pull/400) - enhance Android media player notification window
|
||||
chore: [378](https://github.com/CappielloAntonio/tempo/pull/378) Polish translation
|
||||
Moved details to [CHANGELOG.md](https://github.com/eddyizm/tempo/blob/main/CHANGELOG.md)
|
||||
|
||||
## Features
|
||||
- **Subsonic Integration**: Tempo seamlessly integrates with your Subsonic server, providing you with easy access to your entire music collection on the go.
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ android {
|
|||
minSdkVersion 24
|
||||
targetSdk 35
|
||||
|
||||
versionCode 26
|
||||
versionName '3.10.0'
|
||||
versionCode 27
|
||||
versionName '3.11.2'
|
||||
|
||||
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
||||
|
||||
|
|
|
|||
1101
app/schemas/com.cappielloantonio.tempo.database.AppDatabase/11.json
Normal file
1101
app/schemas/com.cappielloantonio.tempo.database.AppDatabase/11.json
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -28,9 +28,9 @@ import com.cappielloantonio.tempo.subsonic.models.Playlist;
|
|||
|
||||
@UnstableApi
|
||||
@Database(
|
||||
version = 10,
|
||||
version = 11,
|
||||
entities = {Queue.class, Server.class, RecentSearch.class, Download.class, Chronology.class, Favorite.class, SessionMediaItem.class, Playlist.class},
|
||||
autoMigrations = {@AutoMigration(from = 9, to = 10)}
|
||||
autoMigrations = {@AutoMigration(from = 10, to = 11)}
|
||||
)
|
||||
@TypeConverters({DateConverters.class})
|
||||
public abstract class AppDatabase extends RoomDatabase {
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ class Chronology(@PrimaryKey override val id: String) : Child(id) {
|
|||
transcodedSuffix = mediaItem.mediaMetadata.extras!!.getString("transcodedSuffix")
|
||||
duration = mediaItem.mediaMetadata.extras!!.getInt("duration")
|
||||
bitrate = mediaItem.mediaMetadata.extras!!.getInt("bitrate")
|
||||
samplingRate = mediaItem.mediaMetadata.extras!!.getInt("samplingRate")
|
||||
bitDepth = mediaItem.mediaMetadata.extras!!.getInt("bitDepth")
|
||||
path = mediaItem.mediaMetadata.extras!!.getString("path")
|
||||
isVideo = mediaItem.mediaMetadata.extras!!.getBoolean("isVideo")
|
||||
userRating = mediaItem.mediaMetadata.extras!!.getInt("userRating")
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ class Queue(override val id: String) : Child(id) {
|
|||
transcodedSuffix = child.transcodedSuffix
|
||||
duration = child.duration
|
||||
bitrate = child.bitrate
|
||||
samplingRate = child.samplingRate
|
||||
bitDepth = child.bitDepth
|
||||
path = child.path
|
||||
isVideo = child.isVideo
|
||||
userRating = child.userRating
|
||||
|
|
|
|||
|
|
@ -50,6 +50,12 @@ open class Child(
|
|||
@ColumnInfo("bitrate")
|
||||
@SerializedName("bitRate")
|
||||
var bitrate: Int? = null,
|
||||
@ColumnInfo("sampling_rate")
|
||||
@SerializedName("samplingRate")
|
||||
var samplingRate: Int? = null,
|
||||
@ColumnInfo("bit_depth")
|
||||
@SerializedName("bitDepth")
|
||||
var bitDepth: Int? = null,
|
||||
@ColumnInfo
|
||||
var path: String? = null,
|
||||
@ColumnInfo(name = "is_video")
|
||||
|
|
|
|||
|
|
@ -14,11 +14,20 @@ open class ItemDate : Parcelable {
|
|||
var month: Int? = null
|
||||
var day: Int? = null
|
||||
|
||||
fun getFormattedDate(): String {
|
||||
val calendar = Calendar.getInstance()
|
||||
val dateFormat = SimpleDateFormat("MMMM dd, yyyy", Locale.getDefault())
|
||||
fun getFormattedDate(): String? {
|
||||
if (year == null && month == null && day == null) return null
|
||||
|
||||
calendar.set(year ?: 0, month ?: 0, day ?: 0)
|
||||
val calendar = Calendar.getInstance()
|
||||
val dateFormat = if (month == null && day == null) {
|
||||
SimpleDateFormat("yyyy", Locale.getDefault())
|
||||
} else if (day == null) {
|
||||
SimpleDateFormat("MMMM yyyy", Locale.getDefault())
|
||||
}
|
||||
else{
|
||||
SimpleDateFormat("MMMM dd, yyyy", Locale.getDefault())
|
||||
}
|
||||
|
||||
calendar.set(year ?: 0, month ?: 1, day ?: 1)
|
||||
|
||||
return dateFormat.format(calendar.time)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ public class CacheUtil {
|
|||
NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(network);
|
||||
|
||||
if (capabilities != null) {
|
||||
return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
|
||||
return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,6 +72,8 @@ public class TrackInfoDialog extends DialogFragment {
|
|||
bind.transcodedSuffixValueSector.setText(mediaMetadata.extras.getString("transcodedSuffix", getString(R.string.label_placeholder)));
|
||||
bind.durationValueSector.setText(MusicUtil.getReadableDurationString(mediaMetadata.extras.getInt("duration", 0), false));
|
||||
bind.bitrateValueSector.setText(mediaMetadata.extras.getInt("bitrate", 0) + " kbps");
|
||||
bind.samplingRateValueSector.setText(mediaMetadata.extras.getInt("samplingRate", 0) != 0 ? mediaMetadata.extras.getInt("samplingRate", 0) + " Hz" : getString(R.string.label_placeholder));
|
||||
bind.bitDepthValueSector.setText(mediaMetadata.extras.getInt("bitDepth", 0) != 0 ? mediaMetadata.extras.getInt("bitDepth", 0) + " bits" : getString(R.string.label_placeholder));
|
||||
bind.pathValueSector.setText(mediaMetadata.extras.getString("path", getString(R.string.label_placeholder)));
|
||||
bind.discNumberValueSector.setText(String.valueOf(mediaMetadata.extras.getInt("discNumber", 0)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -145,17 +145,27 @@ public class AlbumPageFragment extends Fragment implements ClickCallback {
|
|||
bind.albumNameLabel.setText(album.getName());
|
||||
bind.albumArtistLabel.setText(album.getArtist());
|
||||
bind.albumReleaseYearLabel.setText(album.getYear() != 0 ? String.valueOf(album.getYear()) : "");
|
||||
bind.albumReleaseYearLabel.setVisibility(album.getYear() != 0 ? View.VISIBLE : View.GONE);
|
||||
bind.albumSongCountDurationTextview.setText(getString(R.string.album_page_tracks_count_and_duration, album.getSongCount(), album.getDuration() != null ? album.getDuration() / 60 : 0));
|
||||
bind.albumGenresTextview.setText(album.getGenre());
|
||||
if (album.getGenre() != null && !album.getGenre().isEmpty()) {
|
||||
bind.albumGenresTextview.setText(album.getGenre());
|
||||
bind.albumGenresTextview.setVisibility(View.VISIBLE);
|
||||
}
|
||||
else{
|
||||
bind.albumGenresTextview.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (album.getReleaseDate() != null && album.getOriginalReleaseDate() != null) {
|
||||
bind.albumReleaseYearsTextview.setVisibility(View.VISIBLE);
|
||||
if (album.getReleaseDate().getFormattedDate() != null || album.getOriginalReleaseDate().getFormattedDate() != null)
|
||||
bind.albumReleaseYearsTextview.setVisibility(View.VISIBLE);
|
||||
else
|
||||
bind.albumReleaseYearsTextview.setVisibility(View.GONE);
|
||||
|
||||
if (album.getReleaseDate() == null || album.getOriginalReleaseDate() == null) {
|
||||
if (album.getReleaseDate().getFormattedDate() == null || album.getOriginalReleaseDate().getFormattedDate() == null) {
|
||||
bind.albumReleaseYearsTextview.setText(getString(R.string.album_page_release_date_label, album.getReleaseDate() != null ? album.getReleaseDate().getFormattedDate() : album.getOriginalReleaseDate().getFormattedDate()));
|
||||
}
|
||||
|
||||
if (album.getReleaseDate() != null && album.getOriginalReleaseDate() != null) {
|
||||
if (album.getReleaseDate().getFormattedDate() != null && album.getOriginalReleaseDate().getFormattedDate() != null) {
|
||||
if (Objects.equals(album.getReleaseDate().getYear(), album.getOriginalReleaseDate().getYear()) && Objects.equals(album.getReleaseDate().getMonth(), album.getOriginalReleaseDate().getMonth()) && Objects.equals(album.getReleaseDate().getDay(), album.getOriginalReleaseDate().getDay())) {
|
||||
bind.albumReleaseYearsTextview.setText(getString(R.string.album_page_release_date_label, album.getReleaseDate().getFormattedDate()));
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -80,13 +80,13 @@ public class HomeFragment extends Fragment {
|
|||
private void initHomePager() {
|
||||
HomePager pager = new HomePager(this);
|
||||
|
||||
pager.addFragment(new HomeTabMusicFragment(), "Music", R.drawable.ic_home);
|
||||
pager.addFragment(new HomeTabMusicFragment(), getString(R.string.home_section_music), R.drawable.ic_home);
|
||||
|
||||
if (Preferences.isPodcastSectionVisible())
|
||||
pager.addFragment(new HomeTabPodcastFragment(), "Podcast", R.drawable.ic_graphic_eq);
|
||||
pager.addFragment(new HomeTabPodcastFragment(), getString(R.string.home_section_podcast), R.drawable.ic_graphic_eq);
|
||||
|
||||
if (Preferences.isRadioSectionVisible())
|
||||
pager.addFragment(new HomeTabRadioFragment(), "Radio", R.drawable.ic_play_for_work);
|
||||
pager.addFragment(new HomeTabRadioFragment(), getString(R.string.home_section_radio), R.drawable.ic_play_for_work);
|
||||
|
||||
bind.homeViewPager.setAdapter(pager);
|
||||
bind.homeViewPager.setOffscreenPageLimit(3);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.cappielloantonio.tempo.ui.fragment;
|
|||
|
||||
import android.content.ComponentName;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
|
@ -40,6 +41,9 @@ import com.google.android.material.elevation.SurfaceColors;
|
|||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@UnstableApi
|
||||
|
|
@ -190,14 +194,23 @@ public class PlayerControllerFragment extends Fragment {
|
|||
if (mediaMetadata.extras != null) {
|
||||
String extension = mediaMetadata.extras.getString("suffix", "Unknown format");
|
||||
String bitrate = mediaMetadata.extras.getInt("bitrate", 0) != 0 ? mediaMetadata.extras.getInt("bitrate", 0) + "kbps" : "Original";
|
||||
String samplingRate = mediaMetadata.extras.getInt("samplingRate", 0) != 0 ? new DecimalFormat("0.#").format(mediaMetadata.extras.getInt("samplingRate", 0) / 1000.0) + "kHz" : "";
|
||||
String bitDepth = mediaMetadata.extras.getInt("bitDepth", 0) != 0 ? mediaMetadata.extras.getInt("bitDepth", 0) + "b" : "";
|
||||
|
||||
playerMediaExtension.setText(extension);
|
||||
|
||||
if (bitrate.equals("Original")) {
|
||||
playerMediaBitrate.setVisibility(View.GONE);
|
||||
} else {
|
||||
List<String> mediaQualityItems = new ArrayList<>();
|
||||
|
||||
if (!bitrate.trim().isEmpty()) mediaQualityItems.add(bitrate);
|
||||
if (!bitDepth.trim().isEmpty()) mediaQualityItems.add(bitDepth);
|
||||
if (!samplingRate.trim().isEmpty()) mediaQualityItems.add(samplingRate);
|
||||
|
||||
String mediaQuality = TextUtils.join(" • ", mediaQualityItems);
|
||||
playerMediaBitrate.setVisibility(View.VISIBLE);
|
||||
playerMediaBitrate.setText(bitrate);
|
||||
playerMediaBitrate.setText(mediaQuality);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,11 +6,13 @@ import android.os.Bundle;
|
|||
import android.os.Handler;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.Layout;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
|
@ -28,6 +30,7 @@ import com.cappielloantonio.tempo.subsonic.models.Line;
|
|||
import com.cappielloantonio.tempo.subsonic.models.LyricsList;
|
||||
import com.cappielloantonio.tempo.util.MusicUtil;
|
||||
import com.cappielloantonio.tempo.util.OpenSubsonicExtensionsUtil;
|
||||
import com.cappielloantonio.tempo.util.Preferences;
|
||||
import com.cappielloantonio.tempo.viewmodel.PlayerBottomSheetViewModel;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
|
|
@ -76,12 +79,16 @@ public class PlayerLyricsFragment extends Fragment {
|
|||
public void onResume() {
|
||||
super.onResume();
|
||||
bindMediaController();
|
||||
requireActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
releaseHandler();
|
||||
if (!Preferences.isDisplayAlwaysOn()) {
|
||||
requireActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -281,10 +288,18 @@ public class PlayerLyricsFragment extends Fragment {
|
|||
}
|
||||
|
||||
private int getScroll(List<Line> lines, Line toHighlight) {
|
||||
int lineHeight = bind.nowPlayingSongLyricsTextView.getLineHeight();
|
||||
int lineCount = getLineCount(lines, toHighlight);
|
||||
int scrollViewHeight = bind.nowPlayingSongLyricsSrollView.getHeight();
|
||||
int startIndex = getStartPosition(lines, toHighlight);
|
||||
Layout layout = bind.nowPlayingSongLyricsTextView.getLayout();
|
||||
if (layout == null) return 0;
|
||||
|
||||
return lineHeight * lineCount < scrollViewHeight / 2 ? 0 : lineHeight * lineCount - scrollViewHeight / 2 + lineHeight;
|
||||
int line = layout.getLineForOffset(startIndex);
|
||||
int lineTop = layout.getLineTop(line);
|
||||
int lineBottom = layout.getLineBottom(line);
|
||||
int lineCenter = (lineTop + lineBottom) / 2;
|
||||
|
||||
int scrollViewHeight = bind.nowPlayingSongLyricsSrollView.getHeight();
|
||||
int scroll = lineCenter - scrollViewHeight / 2;
|
||||
|
||||
return Math.max(scroll, 0);
|
||||
}
|
||||
}
|
||||
|
|
@ -201,12 +201,22 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
|||
localePref.setEntries(entries);
|
||||
localePref.setEntryValues(entryValues);
|
||||
|
||||
localePref.setDefaultValue(entryValues[0]);
|
||||
localePref.setSummary(Locale.forLanguageTag(localePref.getValue()).getDisplayLanguage());
|
||||
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) -> {
|
||||
LocaleListCompat appLocale = LocaleListCompat.forLanguageTags((String) newValue);
|
||||
AppCompatDelegate.setApplicationLocales(appLocale);
|
||||
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;
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@ public class MappingUtil {
|
|||
bundle.putString("transcodedSuffix", media.getTranscodedSuffix());
|
||||
bundle.putInt("duration", media.getDuration() != null ? media.getDuration() : 0);
|
||||
bundle.putInt("bitrate", media.getBitrate() != null ? media.getBitrate() : 0);
|
||||
bundle.putInt("samplingRate", media.getSamplingRate() != null ? media.getSamplingRate() : 0);
|
||||
bundle.putInt("bitDepth", media.getBitDepth() != null ? media.getBitDepth() : 0);
|
||||
bundle.putString("path", media.getPath());
|
||||
bundle.putBoolean("isVideo", media.isVideo());
|
||||
bundle.putInt("userRating", media.getUserRating() != null ? media.getUserRating() : 0);
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import com.cappielloantonio.tempo.repository.DownloadRepository;
|
|||
import com.cappielloantonio.tempo.subsonic.models.Child;
|
||||
|
||||
import java.text.CharacterIterator;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.StringCharacterIterator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
|
@ -163,6 +164,12 @@ public class MusicUtil {
|
|||
" " +
|
||||
child.getBitrate() +
|
||||
"kbps" +
|
||||
" • " +
|
||||
(child.getBitDepth() != null && child.getBitDepth() != 0
|
||||
? child.getBitDepth() + "/" + (child.getSamplingRate() != null ? child.getSamplingRate() / 1000 : "")
|
||||
: (child.getSamplingRate() != null
|
||||
? new DecimalFormat("0.#").format(child.getSamplingRate() / 1000.0) + "kHz"
|
||||
: "")) +
|
||||
" " +
|
||||
child.getSuffix();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import android.graphics.drawable.InsetDrawable;
|
|||
import androidx.core.os.LocaleListCompat;
|
||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||
|
||||
import com.cappielloantonio.tempo.App;
|
||||
import com.cappielloantonio.tempo.R;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
|
@ -15,9 +16,10 @@ import org.xmlpull.v1.XmlPullParserException;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.AbstractMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
|
@ -74,17 +76,32 @@ public class UIUtil {
|
|||
public static Map<String, String> getLangPreferenceDropdownEntries(Context context) {
|
||||
LocaleListCompat localeList = getLocalesFromResources(context);
|
||||
|
||||
Map<String, String> map = new HashMap<>();
|
||||
List<Map.Entry<String, String>> localeArrayList = new ArrayList<>();
|
||||
|
||||
String systemDefaultLabel = App.getContext().getString(R.string.settings_system_language);
|
||||
String systemDefaultValue = "default";
|
||||
|
||||
for (int i = 0; i < localeList.size(); i++) {
|
||||
Locale locale = localeList.get(i);
|
||||
|
||||
if (locale != null) {
|
||||
map.put(Util.toPascalCase(locale.getDisplayName()), locale.toLanguageTag());
|
||||
localeArrayList.add(
|
||||
new AbstractMap.SimpleEntry<>(
|
||||
Util.toPascalCase(locale.getDisplayName()),
|
||||
locale.toLanguageTag()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return map;
|
||||
localeArrayList.sort(Map.Entry.comparingByKey(String.CASE_INSENSITIVE_ORDER));
|
||||
|
||||
LinkedHashMap<String, String> orderedMap = new LinkedHashMap<>();
|
||||
orderedMap.put(systemDefaultLabel, systemDefaultValue);
|
||||
for (Map.Entry<String, String> entry : localeArrayList) {
|
||||
orderedMap.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
return orderedMap;
|
||||
}
|
||||
|
||||
public static String getReadableDate(Date date) {
|
||||
|
|
|
|||
|
|
@ -391,6 +391,58 @@
|
|||
android:text="@string/label_placeholder" />
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
style="@style/Divider"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginVertical="8dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/sampling_rate_info_sector"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/sampling_rate_key_sector"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="4"
|
||||
android:paddingEnd="8dp"
|
||||
android:text="@string/track_info_sampling_rate" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/sampling_rate_value_sector"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="7"
|
||||
android:text="@string/label_placeholder" />
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
style="@style/Divider"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginVertical="8dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/bit_depth_info_sector"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/bit_depth_key_sector"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="4"
|
||||
android:paddingEnd="8dp"
|
||||
android:text="@string/track_info_bit_depth" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/bit_depth_value_sector"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="7"
|
||||
android:text="@string/label_placeholder" />
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
style="@style/Divider"
|
||||
android:layout_gravity="center_vertical"
|
||||
|
|
|
|||
|
|
@ -126,9 +126,11 @@
|
|||
android:layout_marginEnd="18dp"
|
||||
android:text="@string/label_placeholder"
|
||||
android:textAlignment="center"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/album_song_count_duration_textview"
|
||||
|
|
|
|||
|
|
@ -104,6 +104,9 @@
|
|||
<string name="home_rearrangement_dialog_positive_button">Guardar</string>
|
||||
<string name="home_rearrangement_dialog_title">Reorganizar la página de inicio</string>
|
||||
<string name="home_rearrangement_dialog_subtitle">Tenga en cuenta que para que los cambios surtan efecto, hay que reiniciar la aplicación.</string>
|
||||
<string name="home_section_music">Música</string>
|
||||
<string name="home_section_podcast">Pódcasts</string>
|
||||
<string name="home_section_radio">Radio</string>
|
||||
<string name="home_subtitle_best_of">Mejores pistas de tus artistas favoritos</string>
|
||||
<string name="home_subtitle_made_for_you">Iniciar mix desde una cación que te gustó</string>
|
||||
<string name="home_subtitle_new_internet_radio_station">Añadir una nueva emisora de radio</string>
|
||||
|
|
@ -164,6 +167,7 @@
|
|||
<string name="menu_group_by_artist">Artista</string>
|
||||
<string name="settings_image_size">Resolución de la imagen</string>
|
||||
<string name="settings_language">Idioma</string>
|
||||
<string name="settings_system_language">Idioma del sistema</string>
|
||||
<string name="settings_logout_title">Cerrar sesión</string>
|
||||
<string name="settings_github_link">https://github.com/eddyizm/tempo</string>
|
||||
<string name="settings_github_summary">Siga el desarrollo</string>
|
||||
|
|
@ -312,7 +316,9 @@
|
|||
<string name="streaming_cache_storage_internal_dialog_negative_button">Interno</string>
|
||||
<string name="track_info_album">Álbum</string>
|
||||
<string name="track_info_artist">Artista</string>
|
||||
<string name="track_info_bit_depth">Profundidad de bits</string>
|
||||
<string name="track_info_bitrate">Tasa de bits</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_dialog_positive_button">Aceptar</string>
|
||||
<string name="track_info_transcoded_content_type">Tipo de contenido en la transcodificación</string>
|
||||
|
|
|
|||
|
|
@ -105,6 +105,9 @@
|
|||
<string name="home_rearrangement_dialog_positive_button">Save</string>
|
||||
<string name="home_rearrangement_dialog_title">Rearrange home</string>
|
||||
<string name="home_rearrangement_dialog_subtitle">Please note that in order for the changes made to take effect, it is necessary to restart the application.</string>
|
||||
<string name="home_section_music">Music</string>
|
||||
<string name="home_section_podcast">Podcast</string>
|
||||
<string name="home_section_radio">Radio</string>
|
||||
<string name="home_subtitle_best_of">Top songs of your favorite artists</string>
|
||||
<string name="home_subtitle_made_for_you">Start mix from a song you liked</string>
|
||||
<string name="home_subtitle_new_internet_radio_station">Add a new radio</string>
|
||||
|
|
@ -319,6 +322,7 @@
|
|||
<string name="settings_rounded_corner_summary">If enabled, sets a curvature angle for all rendered covers. The changes will take effect on restart.</string>
|
||||
<string name="settings_scan_title">Scan library</string>
|
||||
<string name="settings_scrobble_title">Enable music scrobbling</string>
|
||||
<string name="settings_system_language">System language</string>
|
||||
<string name="settings_share_title">Enable music sharing</string>
|
||||
<string name="settings_streaming_cache_size">Size of streaming cache</string>
|
||||
<string name="settings_streaming_cache_storage_title">Streaming cache storage</string>
|
||||
|
|
@ -395,6 +399,7 @@
|
|||
<string name="support_url">https://buymeacoffee.com/a.cappiello</string>
|
||||
<string name="track_info_album">Album</string>
|
||||
<string name="track_info_artist">Artist</string>
|
||||
<string name="track_info_bit_depth">Bit depth</string>
|
||||
<string name="track_info_bitrate">Bitrate</string>
|
||||
<string name="track_info_content_type">Content Type</string>
|
||||
<string name="track_info_dialog_positive_button">OK</string>
|
||||
|
|
@ -403,6 +408,7 @@
|
|||
<string name="track_info_duration">Duration</string>
|
||||
<string name="track_info_genre">Genre</string>
|
||||
<string name="track_info_path">Path</string>
|
||||
<string name="track_info_sampling_rate">Sampling rate</string>
|
||||
<string name="track_info_size">Size</string>
|
||||
<string name="track_info_suffix">Suffix</string>
|
||||
<string name="track_info_summary_downloaded_file">The file has been downloaded using the Subsonic APIs. The codec and bitrate of the file remain unchanged from the source file.</string>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue