feat: add all songs library view and rebrand fork to tempor

This commit is contained in:
2026-04-01 23:07:12 +03:00
parent a179db6323
commit 4ee1822057
23 changed files with 296 additions and 53 deletions

View File

@@ -47,12 +47,12 @@ android {
productFlavors {
tempus {
dimension = "default"
applicationId 'com.eddyizm.tempus'
applicationId 'ru.benya.tempor'
}
degoogled {
dimension = "default"
applicationId "com.eddyizm.degoogled.tempus"
applicationId "ru.benya.tempor.degoogled"
}
}

View File

@@ -8,15 +8,23 @@ import androidx.lifecycle.MutableLiveData;
import com.cappielloantonio.tempo.App;
import com.cappielloantonio.tempo.subsonic.base.ApiResponse;
import com.cappielloantonio.tempo.subsonic.models.Child;
import com.cappielloantonio.tempo.subsonic.models.Directory;
import com.cappielloantonio.tempo.subsonic.models.Index;
import com.cappielloantonio.tempo.subsonic.models.Indexes;
import com.cappielloantonio.tempo.subsonic.models.MusicFolder;
import com.cappielloantonio.tempo.subsonic.models.SearchResult3;
import com.cappielloantonio.tempo.subsonic.models.SubsonicResponse;
import com.cappielloantonio.tempo.util.Constants.SeedType;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Executors;
import retrofit2.Call;
import retrofit2.Callback;
@@ -60,6 +68,20 @@ public class SongRepository {
return starredSongs;
}
public MutableLiveData<List<Child>> getAllSongs() {
MutableLiveData<List<Child>> allSongs = new MutableLiveData<>(new ArrayList<>());
Executors.newSingleThreadExecutor().execute(() -> {
List<Child> songs = fetchAllSongsViaSearch();
if (songs.isEmpty()) {
songs = fetchAllSongsViaBrowsing();
}
allSongs.postValue(songs);
});
return allSongs;
}
/**
* Used by ViewModels. Updates the LiveData list incrementally as songs are found.
*/
@@ -386,4 +408,148 @@ public class SongRepository {
});
return lyrics;
}
}
private List<Child> fetchAllSongsViaSearch() {
LinkedHashMap<String, Child> songsById = new LinkedHashMap<>();
int offset = 0;
int limit = 500;
while (true) {
try {
Response<ApiResponse> response = App.getSubsonicClientInstance(false)
.getSearchingClient()
.search3("", limit, offset, 0, 0, 0, 0)
.execute();
if (!response.isSuccessful() || response.body() == null) {
break;
}
SearchResult3 searchResult3 = response.body().getSubsonicResponse().getSearchResult3();
List<Child> batch = searchResult3 != null ? searchResult3.getSongs() : null;
if (batch == null || batch.isEmpty()) {
break;
}
for (Child child : batch) {
addPlayableChild(songsById, child);
}
offset += batch.size();
} catch (IOException e) {
Log.e(TAG, "fetchAllSongsViaSearch()", e);
break;
}
}
return new ArrayList<>(songsById.values());
}
private List<Child> fetchAllSongsViaBrowsing() {
LinkedHashMap<String, Child> songsById = new LinkedHashMap<>();
Set<String> visitedDirectories = new HashSet<>();
try {
Response<ApiResponse> musicFoldersResponse = App.getSubsonicClientInstance(false)
.getBrowsingClient()
.getMusicFolders()
.execute();
if (musicFoldersResponse.isSuccessful()
&& musicFoldersResponse.body() != null
&& musicFoldersResponse.body().getSubsonicResponse().getMusicFolders() != null
&& musicFoldersResponse.body().getSubsonicResponse().getMusicFolders().getMusicFolders() != null
&& !musicFoldersResponse.body().getSubsonicResponse().getMusicFolders().getMusicFolders().isEmpty()) {
for (MusicFolder musicFolder : musicFoldersResponse.body().getSubsonicResponse().getMusicFolders().getMusicFolders()) {
collectSongsFromIndexes(musicFolder.getId(), songsById, visitedDirectories);
}
} else {
collectSongsFromIndexes(null, songsById, visitedDirectories);
}
} catch (IOException e) {
Log.e(TAG, "fetchAllSongsViaBrowsing()", e);
}
return new ArrayList<>(songsById.values());
}
private void collectSongsFromIndexes(String musicFolderId, LinkedHashMap<String, Child> songsById, Set<String> visitedDirectories) throws IOException {
Response<ApiResponse> indexesResponse = App.getSubsonicClientInstance(false)
.getBrowsingClient()
.getIndexes(musicFolderId, null)
.execute();
if (!indexesResponse.isSuccessful() || indexesResponse.body() == null) {
return;
}
Indexes indexes = indexesResponse.body().getSubsonicResponse().getIndexes();
if (indexes == null) {
return;
}
if (indexes.getChildren() != null) {
for (Child child : indexes.getChildren()) {
if (child == null) {
continue;
}
if (child.isDir()) {
collectSongsFromDirectory(child.getId(), songsById, visitedDirectories);
} else {
addPlayableChild(songsById, child);
}
}
}
if (indexes.getIndices() != null) {
for (Index index : indexes.getIndices()) {
if (index == null || index.getArtists() == null) {
continue;
}
for (com.cappielloantonio.tempo.subsonic.models.Artist artist : index.getArtists()) {
if (artist != null && artist.getId() != null && !artist.getId().isEmpty()) {
collectSongsFromDirectory(artist.getId(), songsById, visitedDirectories);
}
}
}
}
}
private void collectSongsFromDirectory(String directoryId, LinkedHashMap<String, Child> songsById, Set<String> visitedDirectories) throws IOException {
if (directoryId == null || directoryId.isEmpty() || !visitedDirectories.add(directoryId)) {
return;
}
Response<ApiResponse> directoryResponse = App.getSubsonicClientInstance(false)
.getBrowsingClient()
.getMusicDirectory(directoryId)
.execute();
if (!directoryResponse.isSuccessful() || directoryResponse.body() == null) {
return;
}
Directory directory = directoryResponse.body().getSubsonicResponse().getDirectory();
if (directory == null || directory.getChildren() == null) {
return;
}
for (Child child : directory.getChildren()) {
if (child == null) {
continue;
}
if (child.isDir()) {
collectSongsFromDirectory(child.getId(), songsById, visitedDirectories);
} else {
addPlayableChild(songsById, child);
}
}
}
private void addPlayableChild(LinkedHashMap<String, Child> songsById, Child child) {
if (child == null || child.getId() == null || child.isDir() || child.isVideo()) {
return;
}
songsById.putIfAbsent(child.getId(), child);
}
}

View File

@@ -110,6 +110,11 @@ public class LibraryFragment extends Fragment implements ClickCallback {
}
private void init() {
bind.songCatalogueTextViewClickable.setOnClickListener(v -> {
Bundle bundle = new Bundle();
bundle.putString(Constants.MEDIA_ALL, Constants.MEDIA_ALL);
activity.navController.navigate(R.id.action_libraryFragment_to_songListPageFragment, bundle);
});
bind.albumCatalogueTextViewClickable.setOnClickListener(v -> activity.navController.navigate(R.id.action_libraryFragment_to_albumCatalogueFragment));
bind.artistCatalogueTextViewClickable.setOnClickListener(v -> activity.navController.navigate(R.id.action_libraryFragment_to_artistCatalogueFragment));
bind.genreCatalogueTextViewClickable.setOnClickListener(v -> activity.navController.navigate(R.id.action_libraryFragment_to_genreCatalogueFragment));

View File

@@ -109,6 +109,8 @@ public class SongListPageFragment extends Fragment implements ClickCallback {
}
private void init() {
songListPageViewModel.invalidateSongList();
if (requireArguments().getString(Constants.MEDIA_RECENTLY_PLAYED) != null) {
songListPageViewModel.title = Constants.MEDIA_RECENTLY_PLAYED;
songListPageViewModel.toolbarTitle = getString(R.string.song_list_page_recently_played);
@@ -146,6 +148,10 @@ public class SongListPageFragment extends Fragment implements ClickCallback {
songListPageViewModel.title = Constants.MEDIA_STARRED;
songListPageViewModel.toolbarTitle = getString(R.string.song_list_page_starred);
bind.pageTitleLabel.setText(R.string.song_list_page_starred);
} else if (requireArguments().getString(Constants.MEDIA_ALL) != null) {
songListPageViewModel.title = Constants.MEDIA_ALL;
songListPageViewModel.toolbarTitle = getString(R.string.song_list_page_all);
bind.pageTitleLabel.setText(R.string.song_list_page_all);
} else if (requireArguments().getString(Constants.MEDIA_DOWNLOADED) != null) {
songListPageViewModel.title = Constants.MEDIA_DOWNLOADED;
songListPageViewModel.toolbarTitle = getString(R.string.song_list_page_downloaded);
@@ -302,6 +308,7 @@ public class SongListPageFragment extends Fragment implements ClickCallback {
case Constants.MEDIA_BY_ARTIST:
case Constants.MEDIA_BY_GENRES:
case Constants.MEDIA_STARRED:
case Constants.MEDIA_ALL:
bind.pageSubtitleLabel.setText(getString(R.string.generic_list_page_count, children.size()));
break;
}
@@ -316,6 +323,7 @@ public class SongListPageFragment extends Fragment implements ClickCallback {
case Constants.MEDIA_BY_ARTIST:
case Constants.MEDIA_BY_GENRES:
case Constants.MEDIA_STARRED:
case Constants.MEDIA_ALL:
bind.songListSortImageView.setVisibility(View.VISIBLE);
break;
}
@@ -367,4 +375,4 @@ public class SongListPageFragment extends Fragment implements ClickCallback {
private void setMediaBrowserListenableFuture() {
songHorizontalAdapter.setMediaBrowserListenableFuture(mediaBrowserListenableFuture);
}
}
}

View File

@@ -70,6 +70,7 @@ object Constants {
const val MEDIA_BY_ARTIST = "MEDIA_BY_ARTIST"
const val MEDIA_BY_YEAR = "MEDIA_BY_YEAR"
const val MEDIA_STARRED = "MEDIA_STARRED"
const val MEDIA_ALL = "MEDIA_ALL"
const val MEDIA_DOWNLOADED = "MEDIA_DOWNLOADED"
const val MEDIA_FROM_ALBUM = "MEDIA_FROM_ALBUM"
const val MEDIA_MIX = "MEDIA_MIX"
@@ -130,4 +131,4 @@ object Constants {
enum class SeedType {
ARTIST, ALBUM, TRACK
}
}
}

View File

@@ -47,6 +47,10 @@ public class SongListPageViewModel extends AndroidViewModel {
}
public LiveData<List<Child>> getSongList() {
if (songList != null) {
return songList;
}
songList = new MutableLiveData<>(new ArrayList<>());
switch (title) {
@@ -65,6 +69,9 @@ public class SongListPageViewModel extends AndroidViewModel {
case Constants.MEDIA_STARRED:
songList = songRepository.getStarredSongs(false, -1);
break;
case Constants.MEDIA_ALL:
songList = songRepository.getAllSongs();
break;
}
return songList;
@@ -90,10 +97,15 @@ public class SongListPageViewModel extends AndroidViewModel {
case Constants.MEDIA_BY_GENRES:
case Constants.MEDIA_BY_YEAR:
case Constants.MEDIA_STARRED:
case Constants.MEDIA_ALL:
break;
}
}
public void invalidateSongList() {
songList = null;
}
public String getFiltersTitle() {
return TextUtils.join(", ", filterNames);
}

View File

@@ -30,6 +30,48 @@
android:orientation="vertical"
android:paddingBottom="@dimen/global_padding_bottom">
<LinearLayout
android:id="@+id/library_song_sector"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:visibility="visible">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingStart="8dp"
android:paddingTop="16dp"
android:paddingEnd="8dp"
android:paddingBottom="8dp">
<TextView
style="@style/TitleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="8dp"
android:paddingEnd="8dp"
android:text="@string/library_title_song" />
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
<TextView
android:id="@+id/song_catalogue_text_view_clickable"
style="@style/TitleMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|center_vertical"
android:paddingStart="8dp"
android:paddingEnd="8dp"
android:text="@string/library_title_song_see_all_button" />
</LinearLayout>
</LinearLayout>
<!-- Music Folder -->
<LinearLayout
android:id="@+id/library_music_folder_sector"
@@ -355,4 +397,4 @@
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -29,7 +29,7 @@
<string name="album_page_release_dates_label">Publicació: %1$s, originalment: %2$s</string>
<string name="album_page_shuffle_button">Reprodueix aleatòriament</string>
<string name="album_page_tracks_count_and_duration">%1$d cançons • %2$d minuts</string>
<string name="app_name">Tempus</string>
<string name="app_name">Tempor</string>
<string name="artist_adapter_radio_station_starting">S\'està cercant...</string>
<string name="artist_bottom_sheet_instant_mix">Mescla instantània</string>
<string name="artist_bottom_sheet_shuffle">Reprodueix aleatòriament</string>
@@ -534,4 +534,4 @@
<string name="settings_album_detail_summary">Si s\'habilita, es mostren els detalls de l\'àlbum, com el gènere i el nombre de cançons, a la pàgina de l\'àlbum.</string>
<string name="settings_artist_sort_by_album_count">Ordena els artistes per nombre d\'àlbums</string>
<string name="settings_artist_sort_by_album_count_summary">Si s\'habilita, ordena els artistes per nombre d\'àlbums. Si no, s\'ordenen per nom.</string>
</resources>
</resources>

View File

@@ -28,7 +28,7 @@
<string name="album_page_release_dates_label">Veröffentlicht am %1$s, ursprünglich %2$s</string>
<string name="album_page_shuffle_button">Zufällige Wiedergabe</string>
<string name="album_page_tracks_count_and_duration">%1$d Tracks • %2$d Minuten</string>
<string name="app_name">Tempus</string>
<string name="app_name">Tempor</string>
<string name="artist_adapter_radio_station_starting">Suche…</string>
<string name="artist_bottom_sheet_instant_mix">Instant mix</string>
<string name="artist_bottom_sheet_shuffle">Mischen</string>
@@ -416,4 +416,4 @@
<string name="track_info_summary_transcoding_codec">Tempus wird den Server bitten, die Datei zu transkodieren. Der vom Benutzer gewünschte Codec ist %1$s, die Bitrate wird dieselbe wie bei der original Datei sein. Die potentielle Transkodierung der Datei in das gewünschte Format ist vom Server abhängig. Dieser kann die Operation gegebenenfalls nicht unterstützen.</string>
<string name="track_info_summary_transcoding_bitrate">Tempus wird den Server bitten, die Bitrate der Datei zu erändern. Die vom Benutzer gewünschte Bitrate ist %1$s, der Codec der Originaldatei wird nicht verändert. Änderungen an der Bitrate der Datei werden vom Server ausgeführt, dieser kann die Operation gegebenenfalls nicht unterstützen.</string>
<string name="track_info_summary_full_transcode">Die Anwendung wird den Server bitten die Datei zu transkodieren und die Bitrate zu verändern. Der vom Benutzer gewünschte Codec ist %1$s, mit der Bitrate %2$s. Änderungen am Codec und an der Bitrate der Datei werden vom Server ausgeführt, dieser kann die Operation gegebenenfalls nicht unterstützen.</string>
</resources>
</resources>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<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">Tempor</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_summary">Por favor, desactiva las optimizaciones de batería para continuar la reproducción multimedia mientras la pantalla está apagada.</string>
@@ -575,4 +575,4 @@
<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>

View File

@@ -46,7 +46,7 @@
<string name="album_page_release_dates_label">Sorti le %1$s, initialement %2$s</string>
<string name="album_page_shuffle_button">Mélanger</string>
<string name="album_page_tracks_count_and_duration">%1$d titres • %2$d minutes</string>
<string name="app_name">Tempus</string>
<string name="app_name">Tempor</string>
<string name="artist_adapter_radio_station_starting">Recherche…</string>
<string name="artist_bottom_sheet_instant_mix">Mix instantané</string>
<string name="artist_bottom_sheet_shuffle">Mélanger</string>

View File

@@ -28,7 +28,7 @@
<string name="album_page_release_dates_label">Rilasciato il %1$s, originariamente il %2$s</string>
<string name="album_page_shuffle_button">Riproduzione casuale</string>
<string name="album_page_tracks_count_and_duration">%1$d brani • %2$d minuti</string>
<string name="app_name">Tempus</string>
<string name="app_name">Tempor</string>
<string name="artist_adapter_radio_station_starting">Cercando…</string>
<string name="artist_bottom_sheet_instant_mix">Mix istantaneo</string>
<string name="artist_bottom_sheet_shuffle">Riproduzione casuale</string>

View File

@@ -27,7 +27,7 @@
<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="app_name">Tempor</string>
<string name="artist_adapter_radio_station_starting">탐색 중…</string>
<string name="artist_bottom_sheet_instant_mix">인스턴트 믹스</string>
<string name="artist_bottom_sheet_shuffle">셔플</string>

View File

@@ -45,7 +45,7 @@
<string name="album_page_release_dates_label">Wydane %1$s, oryginalnie %2$s</string>
<string name="album_page_shuffle_button">Odtwarzaj losowo</string>
<string name="album_page_tracks_count_and_duration">%1$d utworów • %2$d minut</string>
<string name="app_name">Tempus</string>
<string name="app_name">Tempor</string>
<string name="artist_adapter_radio_station_starting">Szukanie…</string>
<string name="artist_bottom_sheet_instant_mix">Natychmiastowy mix mix</string>
<string name="artist_bottom_sheet_shuffle">Odtwórz losowo</string>

View File

@@ -25,7 +25,7 @@
<string name="album_page_extra_info_button">Sugestões semelhantes</string>
<string name="album_page_play_button">Reproduzir</string>
<string name="album_page_shuffle_button">Aleatório</string>
<string name="app_name">Tempus</string>
<string name="app_name">Tempor</string>
<string name="artist_adapter_radio_station_starting">Procurando…</string>
<string name="artist_bottom_sheet_instant_mix">Mixagem instantânea</string>
<string name="artist_bottom_sheet_shuffle">Aleatório</string>

View File

@@ -29,7 +29,7 @@
<string name="album_page_release_dates_label">Lansat pe %1$s, inițial %2$s</string>
<string name="album_page_shuffle_button">Amestecare</string>
<string name="album_page_tracks_count_and_duration">%1$d cântece • %2$d minute</string>
<string name="app_name">Tempus</string>
<string name="app_name">Tempor</string>
<string name="artist_adapter_radio_station_starting">Se caută…</string>
<string name="artist_bottom_sheet_instant_mix">Mix instant</string>
<string name="artist_bottom_sheet_shuffle">Amestecare</string>

View File

@@ -46,7 +46,7 @@
<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="app_name">Tempor</string>
<string name="artist_adapter_radio_station_starting">Поиск…</string>
<string name="artist_bottom_sheet_instant_mix">Мгновенный микс</string>
<string name="artist_bottom_sheet_shuffle">Перемешать</string>
@@ -332,22 +332,22 @@
<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_summary">Tempor — это легкий музыкальный клиент с открытым исходным кодом для Subsonic, разработанный специально под Android.</string>
<string name="settings_about_title">О приложении</string>
<string name="settings_always_on_display">Always On Display</string>
<string name="settings_allow_playlist_duplicates">Разрешить дубликаты в плейлистах</string>
<string name="settings_allow_playlist_duplicates_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_summary">Если включено, Tempor не будет принудительно скачивать трек с настройками транскодирования, указанными ниже.</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_summary">Если включено, Tempor будет скачивать треки в транскодированном виде.</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">Формат транскод. в моб. сети 4G/5G</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_summary">Если включено, Tempor не будет принудительно стримить трек с настройками транскодирования, указанными ниже.</string>
<string name="settings_audio_transcode_priority_title">Приоритет серверных настроек транскодирования</string>
<string name="settings_audio_transcode_priority_toast">Приоритет транскодирования передан серверу</string>
<string name="settings_buffering_strategy">Стратегия буферизации</string>
@@ -478,7 +478,7 @@
<string name="share_subtitle_item">Срок действия: %1$s</string>
<string name="share_no_expiration">Никогда</string>
<string name="share_unsupported_error">Общий доступ не поддерживается или не включен</string>
<string name="asset_link_clipboard_label">Ссылка Tempus</string>
<string name="asset_link_clipboard_label">Ссылка Tempor</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>
@@ -517,6 +517,7 @@
<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_all">Все треки</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>
@@ -564,9 +565,9 @@
<string name="undraw_thanks">Особая благодарность команде unDraw за иллюстрации, которые помогли сделать приложение красивее</string>
<string name="widget_label">Tempus Widget</string>
<string name="widget_label">Виджет Tempor</string>
<string name="widget_not_playing">Ничего не воспроизводится</string>
<string name="widget_placeholder_subtitle">Открыть Tempus</string>
<string name="widget_placeholder_subtitle">Открыть Tempor</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>
@@ -605,4 +606,9 @@
<string name="search_sort_title">Сортировать недавние поиски по времени</string>
<string name="search_sort_summary">Если включено, поиски сортируются по времени. Если отключено - по имени.</string>
<string name="library_title_song">Треки</string>
<string name="library_title_song_see_all_button">Все треки</string>
<string name="search_all_songs_loading">Загрузка всех треков…</string>
<string name="search_all_songs">все %1$s треков</string>
<string name="search_all_songs_play">Воспроизвести %1$s</string>
</resources>

View File

@@ -28,7 +28,7 @@
<string name="album_page_release_dates_label">%1$s tarihinde yayınlandı, orijinali %2$s</string>
<string name="album_page_shuffle_button">Karıştır</string>
<string name="album_page_tracks_count_and_duration">%1$d parça • %2$d dakika</string>
<string name="app_name">Tempus</string>
<string name="app_name">Tempor</string>
<string name="artist_adapter_radio_station_starting">Aranıyor…</string>
<string name="artist_bottom_sheet_instant_mix">Anında karışım</string>
<string name="artist_bottom_sheet_shuffle">Karıştır</string>

View File

@@ -28,7 +28,7 @@
<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="app_name">Tempor</string>
<string name="artist_adapter_radio_station_starting">正在搜尋...</string>
<string name="artist_bottom_sheet_instant_mix">即時混聽</string>
<string name="artist_bottom_sheet_shuffle">隨機播放</string>

View File

@@ -28,7 +28,7 @@
<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="app_name">Tempor</string>
<string name="artist_adapter_radio_station_starting">正在搜索...</string>
<string name="artist_bottom_sheet_instant_mix">即时混听</string>
<string name="artist_bottom_sheet_shuffle">随机播放</string>

View File

@@ -47,7 +47,7 @@
<string name="album_page_release_dates_label">Released on %1$s, originally %2$s</string>
<string name="album_page_shuffle_button">Shuffle</string>
<string name="album_page_tracks_count_and_duration">%1$d songs • %2$d minutes</string>
<string name="app_name">Tempus</string>
<string name="app_name">Tempor</string>
<string name="artist_adapter_radio_station_starting">Searching…</string>
<string name="artist_bottom_sheet_instant_mix">Instant mix</string>
<string name="artist_bottom_sheet_shuffle">Shuffle</string>
@@ -333,22 +333,22 @@
<string name="server_unreachable_dialog_positive_button">Continue anyway</string>
<string name="server_unreachable_dialog_summary">The requested server is unavailable. If you choose to continue this dialog will not appear for the next hour.</string>
<string name="server_unreachable_dialog_title">Server unreachable</string>
<string name="settings_about_summary">Tempus is an open source and lightweight music client for Subsonic, designed and built natively for Android.</string>
<string name="settings_about_summary">Tempor is an open source and lightweight music client for Subsonic, designed and built natively for Android.</string>
<string name="settings_about_title">About</string>
<string name="settings_always_on_display">Always on display</string>
<string name="settings_allow_playlist_duplicates">Allow adding duplicates to playlist</string>
<string name="settings_allow_playlist_duplicates_summary">If enabled, duplicates won\'t be checked while adding to a playlist.</string>
<string name="settings_audio_transcode_download_format">Transcode format</string>
<string name="settings_audio_transcode_download_priority_summary">If enabled, Tempus will not force download the track with the transcode settings below.</string>
<string name="settings_audio_transcode_download_priority_summary">If enabled, Tempor will not force download the track with the transcode settings below.</string>
<string name="settings_audio_transcode_download_priority_title">Prioritize server settings used for streaming in downloads</string>
<string name="settings_audio_transcode_download_summary">If enabled, Tempus will download transcoded tracks.</string>
<string name="settings_audio_transcode_download_summary">If enabled, Tempor will download transcoded tracks.</string>
<string name="settings_audio_transcode_download_title">Download transcoded tracks</string>
<string name="settings_audio_transcode_estimate_content_length_summary">If enabled, the server will be asked for the estimated duration of the track.</string>
<string name="settings_audio_transcode_estimate_content_length_title">Estimate content length</string>
<string name="settings_audio_transcode_format_download">Transcode format for downloads</string>
<string name="settings_audio_transcode_format_mobile">Transcode format in mobile</string>
<string name="settings_audio_transcode_format_wifi">Transcode format in Wi-Fi</string>
<string name="settings_audio_transcode_priority_summary">If enabled, Tempus will not force stream the track with the transcode settings below.</string>
<string name="settings_audio_transcode_priority_summary">If enabled, Tempor will not force stream the track with the transcode settings below.</string>
<string name="settings_audio_transcode_priority_title">Prioritize server transcode settings</string>
<string name="settings_audio_transcode_priority_toast">Priority on transcoding of track given to server</string>
<string name="settings_buffering_strategy">Buffering strategy</string>
@@ -480,7 +480,7 @@
<string name="share_subtitle_item">Expiration date: %1$s</string>
<string name="share_no_expiration">Never</string>
<string name="share_unsupported_error">Sharing is not supported or not enabled</string>
<string name="asset_link_clipboard_label">Tempus asset link</string>
<string name="asset_link_clipboard_label">Tempor asset link</string>
<string name="asset_link_label_song">Song UID</string>
<string name="asset_link_label_album">Album UID</string>
<string name="asset_link_label_artist">Artist UID</string>
@@ -519,6 +519,7 @@
<string name="song_list_page_recently_added">Recently added tracks</string>
<string name="song_list_page_recently_played">Recently played tracks</string>
<string name="song_list_page_starred">Starred tracks</string>
<string name="song_list_page_all">All songs</string>
<string name="song_list_page_top">%1$s\'s top tracks</string>
<string name="song_list_page_year">Year %1$d</string>
<string name="song_subtitle_formatter">%1$s • %2$s %3$s</string>
@@ -566,9 +567,9 @@
<string name="undraw_page">unDraw</string>
<string name="undraw_thanks">A special thanks goes to unDraw without whose illustrations we could not have made this application more beautiful.</string>
<string name="undraw_url" translatable="false">https://undraw.co/</string>
<string name="widget_label">Tempus Widget</string>
<string name="widget_label">Tempor Widget</string>
<string name="widget_not_playing">Not playing</string>
<string name="widget_placeholder_subtitle">Open Tempus</string>
<string name="widget_placeholder_subtitle">Open Tempor</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">Album artwork</string>
@@ -607,7 +608,9 @@
<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_all_songs_loading">Getting all songs ...</string>
<string name="library_title_song">Songs</string>
<string name="library_title_song_see_all_button">All songs</string>
<string name="search_all_songs_loading">Loading all songs…</string>
<string name="search_all_songs">all %1$s songs</string>
<string name="search_all_songs_play">Play %1$s</string>
</resources>