Merge branch 'development' into tempus-readme-update

This commit is contained in:
eddyizm 2025-10-20 12:22:25 -07:00
commit be0480538e
No known key found for this signature in database
GPG key ID: CF5F671829E8158A
7 changed files with 125 additions and 20 deletions

View file

@ -45,7 +45,7 @@ jobs:
bash ./gradlew assembleTempoDebug bash ./gradlew assembleTempoDebug
bash ./gradlew assembleNotquitemyDebug bash ./gradlew assembleNotquitemyDebug
- name: Sign Tempo Release APKs - name: Sign All Tempo Release APKs
id: sign_tempo_release id: sign_tempo_release
uses: r0adkll/sign-android-release@v1 uses: r0adkll/sign-android-release@v1
with: with:
@ -54,10 +54,11 @@ jobs:
alias: ${{ secrets.KEY_ALIAS_GITHUB }} alias: ${{ secrets.KEY_ALIAS_GITHUB }}
keyStorePassword: ${{ secrets.KEYSTORE_PASSWORD }} keyStorePassword: ${{ secrets.KEYSTORE_PASSWORD }}
keyPassword: ${{ secrets.KEY_PASSWORD_GITHUB }} keyPassword: ${{ secrets.KEY_PASSWORD_GITHUB }}
apkPath: "**/*.apk"
env: env:
BUILD_TOOLS_VERSION: ${{ env.BUILD_TOOL_VERSION }} BUILD_TOOLS_VERSION: ${{ env.BUILD_TOOL_VERSION }}
- name: Sign NotQuiteMy Release APKs - name: Sign All NotQuiteMy Release APKs
id: sign_notquitemy_release id: sign_notquitemy_release
uses: r0adkll/sign-android-release@v1 uses: r0adkll/sign-android-release@v1
with: with:
@ -66,9 +67,38 @@ jobs:
alias: ${{ secrets.KEY_ALIAS_GITHUB }} alias: ${{ secrets.KEY_ALIAS_GITHUB }}
keyStorePassword: ${{ secrets.KEYSTORE_PASSWORD }} keyStorePassword: ${{ secrets.KEYSTORE_PASSWORD }}
keyPassword: ${{ secrets.KEY_PASSWORD_GITHUB }} keyPassword: ${{ secrets.KEY_PASSWORD_GITHUB }}
apkPath: "**/*.apk"
env: env:
BUILD_TOOLS_VERSION: ${{ env.BUILD_TOOL_VERSION }} BUILD_TOOLS_VERSION: ${{ env.BUILD_TOOL_VERSION }}
- name: Rename and Prepare APK Files
run: |
# Copy and rename tempo APKs
for file in app/build/outputs/apk/tempo/release/*.apk; do
if [[ $file == *"arm64-v8a"* ]]; then
cp "$file" "./app-tempo-arm64-v8a-release.apk"
echo "Created: app-tempo-arm64-v8a-release.apk"
elif [[ $file == *"armeabi-v7a"* ]]; then
cp "$file" "./app-tempo-armeabi-v7a-release.apk"
echo "Created: app-tempo-armeabi-v7a-release.apk"
fi
done
# Copy and rename notquitemy APKs
for file in app/build/outputs/apk/notquitemy/release/*.apk; do
if [[ $file == *"arm64-v8a"* ]]; then
cp "$file" "./app-notquitemy-arm64-v8a-release.apk"
echo "Created: app-notquitemy-arm64-v8a-release.apk"
elif [[ $file == *"armeabi-v7a"* ]]; then
cp "$file" "./app-notquitemy-armeabi-v7a-release.apk"
echo "Created: app-notquitemy-armeabi-v7a-release.apk"
fi
done
# List the created files for verification
echo "Final APK files:"
ls -la *.apk
- name: Create Release - name: Create Release
id: create_release id: create_release
uses: actions/create-release@v1 uses: actions/create-release@v1
@ -79,24 +109,44 @@ jobs:
env: env:
GITHUB_TOKEN: ${{ github.token }} GITHUB_TOKEN: ${{ github.token }}
- name: Upload Release APKs - name: Upload Tempo 64-bit Release APK
uses: actions/upload-release-asset@v1 uses: actions/upload-release-asset@v1
env: env:
GITHUB_TOKEN: ${{ github.token }} GITHUB_TOKEN: ${{ github.token }}
with: with:
upload_url: ${{ steps.create_release.outputs.upload_url }} upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ${{steps.sign_tempo_release.outputs.signedReleaseFile}} asset_path: ./app-tempo-arm64-v8a-release.apk
asset_name: app-tempo-release.apk asset_name: app-tempo-arm64-v8a-release.apk
asset_content_type: application/vnd.android.package-archive asset_content_type: application/vnd.android.package-archive
- name: Upload NotQuiteMy Release APK - name: Upload Tempo 32-bit Release APK
uses: actions/upload-release-asset@v1 uses: actions/upload-release-asset@v1
env: env:
GITHUB_TOKEN: ${{ github.token }} GITHUB_TOKEN: ${{ github.token }}
with: with:
upload_url: ${{ steps.create_release.outputs.upload_url }} upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ${{steps.sign_notquitemy_release.outputs.signedReleaseFile}} asset_path: ./app-tempo-armeabi-v7a-release.apk
asset_name: app-notquitemy-release.apk asset_name: app-tempo-armeabi-v7a-release.apk
asset_content_type: application/vnd.android.package-archive
- name: Upload NotQuiteMy 64-bit Release APK
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ github.token }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./app-notquitemy-arm64-v8a-release.apk
asset_name: app-notquitemy-arm64-v8a-release.apk
asset_content_type: application/vnd.android.package-archive
- name: Upload NotQuiteMy 32-bit Release APK
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ github.token }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./app-notquitemy-armeabi-v7a-release.apk
asset_name: app-notquitemy-armeabi-v7a-release.apk
asset_content_type: application/vnd.android.package-archive asset_content_type: application/vnd.android.package-archive
- name: Upload Debug APKs as artifacts - name: Upload Debug APKs as artifacts
@ -113,6 +163,8 @@ jobs:
with: with:
name: release-apks name: release-apks
path: | path: |
${{steps.sign_tempo_release.outputs.signedReleaseFile}} ./app-tempo-arm64-v8a-release.apk
${{steps.sign_notquitemy_release.outputs.signedReleaseFile}} ./app-tempo-armeabi-v7a-release.apk
./app-notquitemy-arm64-v8a-release.apk
./app-notquitemy-armeabi-v7a-release.apk
retention-days: 30 retention-days: 30

View file

@ -152,6 +152,12 @@ public class AlbumCatalogueAdapter extends RecyclerView.Adapter<AlbumCatalogueAd
} }
} }
public void setItemsWithoutFilter(List<AlbumID3> albums) {
this.albumsFull = new ArrayList<>(albums);
this.albums = new ArrayList<>(albums);
notifyDataSetChanged();
}
public void sort(String order) { public void sort(String order) {
if (albums == null) return; if (albums == null) return;

View file

@ -3,6 +3,7 @@ package com.cappielloantonio.tempo.ui.fragment;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
@ -35,6 +36,10 @@ import com.cappielloantonio.tempo.util.Constants;
import com.cappielloantonio.tempo.util.Preferences; import com.cappielloantonio.tempo.util.Preferences;
import com.cappielloantonio.tempo.viewmodel.AlbumCatalogueViewModel; import com.cappielloantonio.tempo.viewmodel.AlbumCatalogueViewModel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@OptIn(markerClass = UnstableApi.class) @OptIn(markerClass = UnstableApi.class)
public class AlbumCatalogueFragment extends Fragment implements ClickCallback { public class AlbumCatalogueFragment extends Fragment implements ClickCallback {
private static final String TAG = "AlbumCatalogueFragment"; private static final String TAG = "AlbumCatalogueFragment";
@ -45,15 +50,33 @@ public class AlbumCatalogueFragment extends Fragment implements ClickCallback {
private AlbumCatalogueAdapter albumAdapter; private AlbumCatalogueAdapter albumAdapter;
private String currentSortOrder; private String currentSortOrder;
private List<com.cappielloantonio.tempo.subsonic.models.AlbumID3> originalAlbums;
@Override @Override
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setHasOptionsMenu(true); setHasOptionsMenu(true);
currentSortOrder = Preferences.getAlbumSortOrder();
initData(); initData();
} }
@Override
public void onResume() {
super.onResume();
String latestSort = Preferences.getAlbumSortOrder();
if (!latestSort.equals(currentSortOrder)) {
currentSortOrder = latestSort;
}
// Re-apply sort when returning to fragment
if (originalAlbums != null && currentSortOrder != null) {
applySortToAlbums(currentSortOrder);
} else {
Log.d(TAG, "onResume - Cannot re-sort, missing data");
}
}
@Override @Override
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
@ -118,8 +141,10 @@ public class AlbumCatalogueFragment extends Fragment implements ClickCallback {
albumAdapter.setStateRestorationPolicy(RecyclerView.Adapter.StateRestorationPolicy.PREVENT_WHEN_EMPTY); albumAdapter.setStateRestorationPolicy(RecyclerView.Adapter.StateRestorationPolicy.PREVENT_WHEN_EMPTY);
bind.albumCatalogueRecyclerView.setAdapter(albumAdapter); bind.albumCatalogueRecyclerView.setAdapter(albumAdapter);
albumCatalogueViewModel.getAlbumList().observe(getViewLifecycleOwner(), albums -> { albumCatalogueViewModel.getAlbumList().observe(getViewLifecycleOwner(), albums -> {
albumAdapter.setItems(albums); originalAlbums = albums;
applySavedSortOrder(); currentSortOrder = Preferences.getAlbumSortOrder();
applySortToAlbums(currentSortOrder);
updateSortIndicator();
}); });
bind.albumCatalogueRecyclerView.setOnTouchListener((v, event) -> { bind.albumCatalogueRecyclerView.setOnTouchListener((v, event) -> {
@ -130,6 +155,16 @@ public class AlbumCatalogueFragment extends Fragment implements ClickCallback {
bind.albumListSortImageView.setOnClickListener(view -> showPopupMenu(view, R.menu.sort_album_popup_menu)); bind.albumListSortImageView.setOnClickListener(view -> showPopupMenu(view, R.menu.sort_album_popup_menu));
} }
private void applySortToAlbums(String sortOrder) {
if (originalAlbums == null) {
return;
}
albumAdapter.setItemsWithoutFilter(originalAlbums);
if (sortOrder != null) {
albumAdapter.sort(sortOrder);
}
}
private void initProgressLoader() { private void initProgressLoader() {
albumCatalogueViewModel.getLoadingStatus().observe(getViewLifecycleOwner(), isLoading -> { albumCatalogueViewModel.getLoadingStatus().observe(getViewLifecycleOwner(), isLoading -> {
if (isLoading) { if (isLoading) {
@ -142,13 +177,6 @@ public class AlbumCatalogueFragment extends Fragment implements ClickCallback {
}); });
} }
private void applySavedSortOrder() {
String savedSortOrder = Preferences.getAlbumSortOrder();
currentSortOrder = savedSortOrder;
albumAdapter.sort(savedSortOrder);
updateSortIndicator();
}
private void updateSortIndicator() { private void updateSortIndicator() {
if (bind == null) return; if (bind == null) return;
@ -235,8 +263,8 @@ public class AlbumCatalogueFragment extends Fragment implements ClickCallback {
if (newSortOrder != null) { if (newSortOrder != null) {
currentSortOrder = newSortOrder; currentSortOrder = newSortOrder;
albumAdapter.sort(newSortOrder);
Preferences.setAlbumSortOrder(newSortOrder); Preferences.setAlbumSortOrder(newSortOrder);
applySortToAlbums(newSortOrder);
updateSortIndicator(); updateSortIndicator();
return true; return true;
} }

View file

@ -248,6 +248,10 @@ public class AlbumPageFragment extends Fragment implements ClickCallback {
bind.albumDetailView.setVisibility(View.GONE); bind.albumDetailView.setVisibility(View.GONE);
} }
}); });
if(Preferences.showAlbumDetail()){
bind.albumDetailView.setVisibility(View.VISIBLE);
}
} }
private void initAlbumInfoTextButton() { private void initAlbumInfoTextButton() {

View file

@ -76,6 +76,7 @@ object Preferences {
private const val EQUALIZER_ENABLED = "equalizer_enabled" private const val EQUALIZER_ENABLED = "equalizer_enabled"
private const val EQUALIZER_BAND_LEVELS = "equalizer_band_levels" private const val EQUALIZER_BAND_LEVELS = "equalizer_band_levels"
private const val MINI_SHUFFLE_BUTTON_VISIBILITY = "mini_shuffle_button_visibility" private const val MINI_SHUFFLE_BUTTON_VISIBILITY = "mini_shuffle_button_visibility"
private const val ALBUM_DETAIL = "album_detail"
private const val ALBUM_SORT_ORDER = "album_sort_order" private const val ALBUM_SORT_ORDER = "album_sort_order"
private const val DEFAULT_ALBUM_SORT_ORDER = Constants.ALBUM_ORDER_BY_NAME private const val DEFAULT_ALBUM_SORT_ORDER = Constants.ALBUM_ORDER_BY_NAME
@ -641,6 +642,11 @@ object Preferences {
return ShortArray(bandCount.toInt()) { i -> parts[i].toShortOrNull() ?: 0 } return ShortArray(bandCount.toInt()) { i -> parts[i].toShortOrNull() ?: 0 }
} }
@JvmStatic
fun showAlbumDetail(): Boolean {
return App.getInstance().preferences.getBoolean(ALBUM_DETAIL, false)
}
@JvmStatic @JvmStatic
fun getAlbumSortOrder(): String { fun getAlbumSortOrder(): String {
return App.getInstance().preferences.getString(ALBUM_SORT_ORDER, DEFAULT_ALBUM_SORT_ORDER) ?: DEFAULT_ALBUM_SORT_ORDER return App.getInstance().preferences.getString(ALBUM_SORT_ORDER, DEFAULT_ALBUM_SORT_ORDER) ?: DEFAULT_ALBUM_SORT_ORDER

View file

@ -523,4 +523,7 @@
<string name="equalizer_not_supported">Not supported on this device</string> <string name="equalizer_not_supported">Not supported on this device</string>
<string name="settings_app_equalizer">Equalizer</string> <string name="settings_app_equalizer">Equalizer</string>
<string name="settings_app_equalizer_summary">Open the built-in equalizer</string> <string name="settings_app_equalizer_summary">Open the built-in equalizer</string>
<string name="settings_album_detail">Show album detail</string>
<string name="settings_album_detail_summary">If enabled, show the album details like genre, song count etc. on the album page</string>
</resources> </resources>

View file

@ -110,6 +110,12 @@
android:summary="@string/settings_music_directory_summary" android:summary="@string/settings_music_directory_summary"
android:key="music_directory_section_visibility" /> android:key="music_directory_section_visibility" />
<SwitchPreference
android:title="@string/settings_album_detail"
android:defaultValue="false"
android:summary="@string/settings_album_detail_summary"
android:key="album_detail" />
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory app:title="@string/settings_title_playlist"> <PreferenceCategory app:title="@string/settings_title_playlist">