Skip to content

Commit e23bc6e

Browse files
committed
Added AVDs for bnv and added download page that relies on workflows + tiny bug fixes kinda
1 parent dfed91e commit e23bc6e

40 files changed

Lines changed: 1084 additions & 396 deletions

.github/workflows/main.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,37 @@ jobs:
128128
-F message_thread_id="4" \
129129
-F document=@"preview-armeabi-v7a-${HASH}.apk" \
130130
-F caption="armeabi-v7a Build"
131+
132+
update_website:
133+
name: Update Website Links
134+
runs-on: ubuntu-latest
135+
needs: build_preview_apk
136+
if: github.event_name != 'pull_request'
137+
permissions:
138+
contents: write
139+
steps:
140+
- name: Checkout code
141+
uses: actions/checkout@v4
142+
with:
143+
fetch-depth: 0
144+
145+
- name: Update HTML placeholders
146+
env:
147+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
148+
run: |
149+
LATEST_TAG=$(gh release view --json tagName -q .tagName || echo "v--.--.--")
150+
LATEST_APK_URL=$(gh release view --json assets -q '.assets[0].url' || echo "https://github.com/${{ github.repository }}/releases")
151+
HASH=${GITHUB_SHA::8}
152+
NIGHTLY_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
153+
154+
sed -i "s|__STABLE_VERSION__|${LATEST_TAG}|g" download.html
155+
sed -i "s|__STABLE_URL__|${LATEST_APK_URL}|g" download.html
156+
sed -i "s|__NIGHTLY_HASH__|#${HASH}|g" download.html
157+
sed -i "s|__NIGHTLY_URL__|${NIGHTLY_URL}|g" download.html
158+
159+
- name: Commit changes
160+
run: |
161+
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
162+
git config --local user.name "github-actions[bot]"
163+
git add download.html
164+
git diff --quiet && git diff --staged --quiet || (git commit -m "chore: update download links [skip ci]" && git push)

app/build.gradle

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,10 @@ android {
5858
}
5959

6060
debug {
61-
initWith(release)
61+
storeFile file(System.getProperty("user.home") + "/.android/debug.keystore")
62+
storePassword "android"
63+
keyAlias "androiddebugkey"
64+
keyPassword "android"
6265
}
6366

6467
preview {

app/src/main/java/com/xapps/media/xmusic/activity/manager/LogicManager.java

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package com.xapps.media.xmusic.activity.manager;
22

33
import android.content.ComponentName;
4+
import android.graphics.drawable.AnimatedVectorDrawable;
5+
import android.graphics.drawable.Drawable;
6+
import android.os.Bundle;
47
import android.os.Handler;
58
import android.os.Looper;
69
import android.view.View;
@@ -9,24 +12,29 @@
912

1013
import androidx.activity.BackEventCompat;
1114
import androidx.activity.OnBackPressedCallback;
15+
import androidx.annotation.OptIn;
1216
import androidx.core.view.ViewKt;
1317
import androidx.fragment.app.FragmentActivity;
1418
import androidx.media3.common.MediaItem;
1519
import androidx.media3.common.Player;
20+
import androidx.media3.common.util.UnstableApi;
1621
import androidx.media3.session.MediaController;
22+
import androidx.media3.session.SessionCommand;
1723
import androidx.media3.session.SessionToken;
1824
import androidx.transition.TransitionManager;
1925
import androidx.transition.TransitionSeekController;
2026

2127
import com.google.android.material.search.SearchView;
2228
import com.google.android.material.transition.MaterialFadeThrough;
29+
import com.google.common.collect.ImmutableList;
2330
import com.xapps.media.xmusic.R;
2431
import com.xapps.media.xmusic.activity.RootActivity;
2532
import com.xapps.media.xmusic.activity.controller.ActivityMediaController;
2633
import com.xapps.media.xmusic.callback.CallbackInterface;
2734
import com.xapps.media.xmusic.data.DataManager;
2835
import com.xapps.media.xmusic.data.RuntimeData;
2936
import com.xapps.media.xmusic.databinding.ActivityRootBinding;
37+
import com.xapps.media.xmusic.lyric.LyricsExtractor;
3038
import com.xapps.media.xmusic.service.XPlayerService;
3139
import com.xapps.media.xmusic.utils.XUtils;
3240
import com.xapps.media.xmusic.widget.ExpressiveSliderLayout;
@@ -126,6 +134,8 @@ public void onStopTrackingTouch(SeekBar seekBar) {
126134
mediaController.seekToNext();
127135
});
128136

137+
binding.expandedPlayer.repeatModeButton.setOnClickListener(v -> handleRepeatButtonClick());
138+
129139
binding.expandedPlayer.toggleView.setExtraOnClickListener(new View.OnClickListener() {
130140
@Override
131141
public void onClick(View _view) {
@@ -152,6 +162,7 @@ public void onClick(View _view) {
152162
transition.setDuration(500);
153163

154164
binding.bottomNavigation.setOnItemSelectedListener(item -> {
165+
155166
uiManager.viewModel.saveBNVPosition(activity.getBinding().bottomNavigation.getSelectedItemId());
156167
if (CallbackInterface.srFrag() == null) return false;
157168
if (CallbackInterface.srFrag().getSearchViewState() == SearchView.TransitionState.SHOWING) return false;
@@ -235,6 +246,30 @@ public void onClick(View _view) {
235246
});
236247
}
237248

249+
private void handleRepeatButtonClick() {
250+
if (activity == null || activity.getController() == null || CallbackInterface.service() == null) return;
251+
switch (activity.getController().getRepeatMode()) {
252+
case Player.REPEAT_MODE_ALL -> {
253+
activity.getController().setRepeatMode(Player.REPEAT_MODE_ONE);
254+
binding.expandedPlayer.repeatModeButton.setIconResource(R.drawable.ic_repeat_one);
255+
binding.expandedPlayer.repeatModeButton.setChecked(true);
256+
}
257+
case Player.REPEAT_MODE_ONE -> {
258+
activity.getController().setRepeatMode(Player.REPEAT_MODE_OFF);
259+
binding.expandedPlayer.repeatModeButton.setIconResource(R.drawable.ic_repeat_off);
260+
binding.expandedPlayer.repeatModeButton.setChecked(false);
261+
}
262+
case Player.REPEAT_MODE_OFF -> {
263+
activity.getController().setRepeatMode(Player.REPEAT_MODE_ALL);
264+
binding.expandedPlayer.repeatModeButton.setIconResource(R.drawable.ic_repeat);
265+
binding.expandedPlayer.repeatModeButton.setChecked(true);
266+
}
267+
default -> {
268+
throw new IllegalStateException("Player repeat mode:" + activity.getController().getRepeatMode() + " not handled");
269+
}
270+
}
271+
}
272+
238273
private void setupCallbacks() {
239274
binding.miniPlayer.setupPredictiveBack(activity);
240275
binding.miniPlayer.addSliderCallback(new ExpressiveSliderLayout.SliderCallback() {
@@ -302,6 +337,7 @@ public void handleOnBackCancelled() {
302337
activity.getOnBackPressedDispatcher().addCallback(activity, lyricsCallback);
303338
}
304339

340+
@OptIn(markerClass = UnstableApi.class)
305341
public void initController(FragmentActivity activity, Consumer<MediaController> onReady, Consumer<Throwable> onError, Runnable onRestore) {
306342

307343
if (sessionToken == null) {
@@ -314,7 +350,7 @@ public void initController(FragmentActivity activity, Consumer<MediaController>
314350
mediaController = c;
315351
controller.setupListener((RootActivity) activity);
316352
onReady.accept(c);
317-
}, e -> onError.accept(e), onRestore);
353+
}, onError::accept, onRestore);
318354
}
319355

320356
public void playSong(int position) {
@@ -340,7 +376,9 @@ private static boolean samePlaylistByPath(MediaController controller, List<Media
340376
MediaItem cItem = controller.getMediaItemAt(i);
341377
MediaItem sItem = serviceItems.get(i);
342378

379+
assert cItem.localConfiguration != null;
343380
String cPath = cItem.localConfiguration.uri.getPath();
381+
assert sItem.localConfiguration != null;
344382
String sPath = sItem.localConfiguration.uri.getPath();
345383

346384
if (!Objects.equals(cPath, sPath)) return false;

app/src/main/java/com/xapps/media/xmusic/activity/manager/UIManager.java

Lines changed: 41 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@
2323
import androidx.fragment.app.Fragment;
2424
import androidx.fragment.app.FragmentActivity;
2525
import androidx.lifecycle.ViewModelProvider;
26+
import androidx.media3.common.Player;
2627
import androidx.transition.TransitionManager;
2728
import androidx.viewpager2.adapter.FragmentStateAdapter;
2829

30+
import com.google.android.material.shape.MaterialShapeDrawable;
2931
import com.google.android.material.transition.MaterialFadeThrough;
3032

3133
import com.xapps.media.xmusic.R;
@@ -165,9 +167,6 @@ private void setupDimensions() {
165167
binding.bottomNavigation.getPaddingBottom()
166168
+ XUtils.getNavigationBarHeight(activity));
167169

168-
169-
binding.expandedPlayer.actionsContainer.setPadding(0, 0, 0, XUtils.getNavigationBarHeight(activity));
170-
171170
return Unit.INSTANCE;
172171
});
173172

@@ -432,26 +431,6 @@ private void computeState() {
432431
}
433432
}
434433

435-
private void resyncState() {
436-
playerHidden =
437-
(layoutState == LAYOUT_STATE_FULL
438-
|| layoutState == LAYOUT_STATE_EXPOSE_TABS
439-
|| layoutState == LAYOUT_STATE_EXPOSE_BNV
440-
|| layoutState == LAYOUT_STATE_EXPOSE_TABS_BNV);
441-
442-
bnvHidden =
443-
(layoutState == LAYOUT_STATE_FULL
444-
|| layoutState == LAYOUT_STATE_EXPOSE_TABS
445-
|| layoutState == LAYOUT_STATE_EXPOSE_PLAYER_ONLY
446-
|| layoutState == LAYOUT_STATE_EXPOSE_PLAYER_TABS);
447-
448-
tabsHidden =
449-
(layoutState == LAYOUT_STATE_FULL
450-
|| layoutState == LAYOUT_STATE_EXPOSE_BNV
451-
|| layoutState == LAYOUT_STATE_EXPOSE_PLAYER
452-
|| layoutState == LAYOUT_STATE_EXPOSE_PLAYER_ONLY);
453-
}
454-
455434
private void hideBnvInternal(boolean hide, boolean animate) {
456435
bnvHidden = hide;
457436
if (animate) {
@@ -669,7 +648,7 @@ public void updateColors() {
669648
GradientDrawable d3 =
670649
(GradientDrawable) binding.expandedPlayer.songInfoText.getBackground();
671650

672-
GradientDrawable d = (GradientDrawable) binding.expandedPlayer.actionsContainer.getBackground();
651+
MaterialShapeDrawable d = (MaterialShapeDrawable) binding.expandedPlayer.floatingToolbarLayout.getBackground();
673652

674653
XSeekbar seekbar = binding.expandedPlayer.songSeekbar;
675654

@@ -685,8 +664,7 @@ public void updateColors() {
685664
int is = XUtils.interpolateColor(oldSurface, surface, f);
686665
int isc = XUtils.interpolateColor(oldSurfaceContainer, surfaceContainer, f);
687666
int io = XUtils.interpolateColor(oldOutline, outline, f);
688-
int iosc =
689-
XUtils.interpolateColor(oldOnSurfaceContainer, onSurfaceContainer, f);
667+
int iosc = XUtils.interpolateColor(oldOnSurfaceContainer, onSurfaceContainer, f);
690668
int ios = XUtils.interpolateColor(oldOnSurface, onSurface, f);
691669

692670
LiveColors.primary = ip;
@@ -728,11 +706,14 @@ public void updateColors() {
728706
binding.collapsedPlayer.action.setBackgroundColor(ip);
729707
binding.collapsedPlayer.action.setRippleColor(ColorStateList.valueOf(ColorUtils.setAlphaComponent(io, 100)));
730708

731-
d.setColor(isc);
709+
d.setFillColor(ColorStateList.valueOf(isc));
732710

733711
binding.expandedPlayer.lyricsButton.setIconTint(ColorStateList.valueOf(isOledTheme? 0xffbdbdbd : iosc));
734712
binding.expandedPlayer.lyricsButton.setRippleColor(ColorStateList.valueOf(io));
735713

714+
binding.expandedPlayer.repeatModeButton.setIconTint(ColorStateList.valueOf(isOledTheme? 0xffbdbdbd : iosc));
715+
binding.expandedPlayer.repeatModeButton.setRippleColor(ColorStateList.valueOf(io));
716+
736717
binding.expandedPlayer.artistBigTitle.setTextColor(iosc);
737718
binding.expandedPlayer.songBigTitle.setTextColor(ios);
738719

@@ -743,22 +724,21 @@ public void updateColors() {
743724
binding.expandedPlayer.totalDurationText.setTextColor(iosc);
744725
binding.expandedPlayer.songInfoText.setTextColor(iosc);
745726
});
746-
va.addListener(
747-
new AnimatorListenerAdapter() {
748-
private boolean canceled;
727+
va.addListener(new AnimatorListenerAdapter() {
728+
private boolean canceled;
749729

750-
@Override
751-
public void onAnimationCancel(Animator animation) {
730+
@Override
731+
public void onAnimationCancel(Animator animation) {
752732
canceled = true;
753733
}
754734

755-
@Override
756-
public void onAnimationEnd(Animator animation) {
757-
if (!canceled) {
735+
@Override
736+
public void onAnimationEnd(Animator animation) {
737+
if (!canceled) {
758738
effectiveOldColors = new HashMap<>(colors);
759-
}
760-
}
761-
});
739+
}
740+
}
741+
});
762742
if (colorAnimator != null) {
763743
colorAnimator.cancel();
764744
}
@@ -933,6 +913,7 @@ public void restoreCoverExpansion() {
933913
}
934914

935915
public void maybeRestoreUIState() {
916+
restoreRepeatButton();
936917
if (viewModel.isDataSaved()) {
937918
int savedState = viewModel.getLayoutState();
938919

@@ -1000,6 +981,27 @@ public void maybeRestoreUIState() {
1000981
}
1001982
}
1002983

984+
private void restoreRepeatButton() {
985+
if (activity == null || activity.getController() == null) return;
986+
switch (activity.getController().getRepeatMode()) {
987+
case Player.REPEAT_MODE_ALL -> {
988+
binding.expandedPlayer.repeatModeButton.setIconResource(R.drawable.ic_repeat);
989+
binding.expandedPlayer.repeatModeButton.setChecked(true);
990+
}
991+
case Player.REPEAT_MODE_ONE -> {
992+
binding.expandedPlayer.repeatModeButton.setIconResource(R.drawable.ic_repeat_one);
993+
binding.expandedPlayer.repeatModeButton.setChecked(true);
994+
}
995+
case Player.REPEAT_MODE_OFF -> {
996+
binding.expandedPlayer.repeatModeButton.setIconResource(R.drawable.ic_repeat_off);
997+
binding.expandedPlayer.repeatModeButton.setChecked(false);
998+
}
999+
default -> {
1000+
throw new IllegalStateException("Player repeat mode:" + String.valueOf(activity.getController().getRepeatMode()) + " not handled");
1001+
}
1002+
}
1003+
}
1004+
10031005
public void saveState() {
10041006
viewModel.setLastPosition(activity.getController().getCurrentMediaItemIndex());
10051007
computeState();
@@ -1012,7 +1014,7 @@ public void loadLyrics(String path) {
10121014
LyricsExtractor.extract(path, lyrics -> {
10131015
if (lyrics != null && !lyrics.isEmpty()) {
10141016
LyricsParser.parse(lyrics, result -> {
1015-
binding.xlyricsView.post(() -> {
1017+
binding.lyricsView.post(() -> {
10161018
binding.lyricsView.setLyrics(result.lines());
10171019
binding.lyricsView.setListener(UIManager.this);
10181020

@@ -1045,7 +1047,6 @@ public void loadSettings() {
10451047
if (isOledTheme) binding.gradientView.setVisibility(View.GONE);
10461048
isBlurOn = DataManager.isBlurOn();
10471049
if (XUtils.areBlursOrDynamicColorsSupported() && !isBlurOn) binding.Coordinator.setRenderEffect(null);
1048-
binding.xlyricsView.updateActiveStates();
10491050
updateFontConfig();
10501051
}
10511052

app/src/main/java/com/xapps/media/xmusic/callback/ServiceCallback.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.xapps.media.xmusic.callback;
22
import androidx.media3.common.MediaItem;
3+
import androidx.media3.session.MediaSession;
4+
35
import java.util.ArrayList;
46
import java.util.Collections;
57
import java.util.List;
@@ -54,4 +56,9 @@ default boolean isPlaying() {
5456
default int getCurrentPosition() {
5557
return -1;
5658
}
59+
60+
default MediaSession getSession() {
61+
return null;
62+
}
63+
5764
}

app/src/main/java/com/xapps/media/xmusic/fragment/MusicListFragment.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.xapps.media.xmusic.fragment;
22

3+
import android.annotation.SuppressLint;
34
import android.content.*;
45
import android.graphics.*;
56
import android.graphics.drawable.*;
@@ -307,6 +308,7 @@ public ViewHolder(View v) {
307308
}
308309
}
309310

311+
@SuppressLint("NotifyDataSetChanged")
310312
public void updateData(ArrayList<Song> a) {
311313
data = a;
312314
notifyDataSetChanged();

0 commit comments

Comments
 (0)