Skip to content

Commit d0e2ee1

Browse files
committed
Refactor music folder storage to embedded Realm object
Replace IList<string> with UserMusicFoldersPreference embedded object in AppStateModel for music folder storage. Update all related services, view models, and UI to use the new structure. Improve SettingsFragment UI with Material Chips and new switches. Refactor artist picker and NowPlayingFragment for better UX and robustness. Bump Realm schema to 20. Remove obsolete code and update ISettingsService accordingly. Includes minor bug fixes and UI improvements.
1 parent 4c84f98 commit d0e2ee1

File tree

21 files changed

+288
-343
lines changed

21 files changed

+288
-343
lines changed

Dimmer/Dimmer.Droid/Utils/DimmerSliderListener.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
namespace Dimmer.Utils;
88

9-
public class DimmerSliderListener : Java.Lang.Object, IBaseOnSliderTouchListener, IBaseOnChangeListener, ILabelFormatter
9+
public class DimmerSliderListener : Java.Lang.Object, IBaseOnSliderTouchListener, IBaseOnChangeListener, ILabelFormatter, View.IOnTouchListener
1010
{
1111
private readonly Action _onDragStart;
1212
private readonly Action<float> _onDragStop;
@@ -77,6 +77,12 @@ public void OnValueChange(Java.Lang.Object slider, float value, bool fromUser)
7777
{
7878
_onValueChange?.Invoke(value, fromUser);
7979
}
80+
81+
public bool OnTouch(View? v, MotionEvent? e)
82+
{
83+
_onDragStart?.Invoke();
84+
return true;
85+
}
8086
}
8187
public enum SliderDataType
8288
{

Dimmer/Dimmer.Droid/ViewModels/BaseViewModelAnd.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,8 @@ protected override async Task ProcessSongChangeAsync(SongModelView value)
674674

675675
public System.Reactive.Subjects.Subject<System.Reactive.Unit> ScrollToCurrentSongRequest { get; }
676676
= new System.Reactive.Subjects.Subject<System.Reactive.Unit>();
677+
[ObservableProperty]
678+
public partial bool OpenMediaUIOnNotificationTap { get; private set; }
677679

678680
// 2. Helper method to trigger it
679681
public void TriggerScrollToCurrentSong()
@@ -732,4 +734,18 @@ public async Task LoadFolderToScanForBackUpFiles()
732734
}
733735

734736
}
737+
738+
internal void ToggleOpenMediaUIOnNotificationTap(bool v)
739+
{
740+
var realm = RealmFactory.GetRealmInstance();
741+
var currentAppModel = realm.All<AppStateModel>().FirstOrDefaultNullSafe();
742+
if (currentAppModel != null)
743+
{
744+
realm.Write(() =>
745+
{
746+
currentAppModel.OpenMediaUIOnNotificationTap = v;
747+
});
748+
OpenMediaUIOnNotificationTap = v;
749+
}
750+
}
735751
}

Dimmer/Dimmer.Droid/ViewsAndPages/NativeViews/Activity/TransitionActivity.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -814,7 +814,8 @@ protected override void OnDestroy()
814814
OnBackInvokedDispatcher.UnregisterOnBackInvokedCallback(_onBackInvokedCallback);
815815
_isBackCallbackRegistered = false;
816816
}
817-
MyViewModel.OnAppClosing();
817+
818+
MyViewModel?.OnAppClosing();
818819
base.OnDestroy();
819820
}
820821

Dimmer/Dimmer.Droid/ViewsAndPages/NativeViews/DimmerLive/LastFMViews/LastFMLoginFragment.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
namespace Dimmer.ViewsAndPages.NativeViews.DimmerLive.LastFMViews;
88

99
using System.Reactive.Disposables;
10-
10+
using Dimmer.UiUtils;
1111
using Dimmer.ViewModel;
12-
using Dimmer.WinUI.UiUtils;
12+
1313
using ProgressBar = Android.Widget.ProgressBar;
1414

1515

Dimmer/Dimmer.Droid/ViewsAndPages/NativeViews/HomePageFragment.cs

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,10 @@ public override View OnCreateView(LayoutInflater inflater, ViewGroup? container,
294294

295295

296296
// --- 5. Extended FAB ---
297+
var vLinearLayout = new LinearLayout(ctx);
298+
299+
300+
297301
fab = new Google.Android.Material.FloatingActionButton.ExtendedFloatingActionButton(ctx);
298302
;
299303
fab.Extended = true;
@@ -308,7 +312,7 @@ public override View OnCreateView(LayoutInflater inflater, ViewGroup? container,
308312
fabParams.SetMargins(0, 0, AppUtil.DpToPx(40), AppUtil.DpToPx(90));
309313
fab.LayoutParameters = fabParams;
310314

311-
SetupSwipeableFab(fab);
315+
SetupClickableFab(fab);
312316

313317

314318
// Add FAB to Root
@@ -319,23 +323,12 @@ public override View OnCreateView(LayoutInflater inflater, ViewGroup? container,
319323

320324
return root;
321325
}
322-
private void SetupSwipeableFab(View view)
326+
private void SetupClickableFab(View view)
323327
{
324-
float startRawX = 0;
325-
float startRawY = 0;
326-
327-
const int SwipeThreshold = 50;
328-
328+
329329
view.Click += (s, e) =>
330330
{
331331

332-
_searchBar.RequestFocusFromTouch();
333-
};
334-
view.LongClickable = true;
335-
view.LongClick += (s, e)
336-
=>
337-
{
338-
339332
if (MyViewModel.CurrentPlayingSongView == null) return;
340333
var requestedSong = MyViewModel.CurrentPlayingSongView;
341334

@@ -346,12 +339,16 @@ private void SetupSwipeableFab(View view)
346339
_songListRecycler?.ScrollToPosition(index);
347340

348341
var specificView = _songListRecycler.FindViewHolderForAdapterPosition(index);
349-
342+
350343
var type = specificView?.GetType();
351344
if (type == null) return;
352345
Debug.WriteLine(type);
353-
354-
346+
};
347+
view.LongClickable = true;
348+
view.LongClick += (s, e)
349+
=>
350+
{
351+
_searchBar.RequestFocusFromTouch();
355352
};
356353
}
357354

Lines changed: 82 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
using AndroidX.Lifecycle;
1+
using Android.Content;
2+
using AndroidX.Lifecycle;
23
using Dimmer.DimmerSearch;
34
using Dimmer.UiUtils;
5+
using Google.Android.Material.Chip;
46

57
namespace Dimmer.ViewsAndPages.NativeViews.Misc;
68

@@ -15,6 +17,7 @@ public ArtistPickerBottomSheet(BaseViewModelAnd vm, string listOfArtistString)
1517

1618
public BaseViewModelAnd MyViewModel { get; }
1719
public List<string> ListOfArtistsInSong { get; }
20+
public TextInputLayout searchInput { get; private set; }
1821

1922
public override View? OnCreateView(LayoutInflater inflater, ViewGroup? container, Bundle? savedInstanceState)
2023
{
@@ -30,72 +33,113 @@ public ArtistPickerBottomSheet(BaseViewModelAnd vm, string listOfArtistString)
3033
layout.AddView(title);
3134

3235
// Search Bar
33-
var searchInput = UiBuilder.CreateInput(context, string.Empty, "");
36+
searchInput = UiBuilder.CreateInput(context, string.Empty, "");
3437
layout.AddView(searchInput);
3538

3639
// RecyclerView for Artists
3740
var recyclerView = new RecyclerView(context);
3841
recyclerView.SetLayoutManager(new LinearLayoutManager(context));
3942
// In a real app, pass your ViewModel's Artist list here
4043

41-
recyclerView.SetAdapter(new SimpleStringAdapter(ListOfArtistsInSong, (selected) => {
42-
// Handle Selection (Callback to parent fragment)
43-
MyViewModel.SearchSongForSearchResultHolder(TQlStaticMethods.PresetQueries.ByArtist(selected));
44-
45-
Toast.MakeText(context, $"Selected {selected}", ToastLength.Short)?.Show();
46-
Dismiss();
47-
}));
44+
recyclerView.SetAdapter(new ArtistBottomSheetRecyclerViewAdapter(ListOfArtistsInSong, MyViewModel, this));
4845

4946
layout.AddView(recyclerView, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MatchParent, 800)); // Fixed height or use weight
5047

5148
return layout;
5249
}
5350

5451
// Simple Adapter for the list
55-
class SimpleStringAdapter : RecyclerView.Adapter
52+
class ArtistBottomSheetRecyclerViewAdapter : RecyclerView.Adapter
5653
{
57-
private List<string> _items;
58-
private Action<string> _onClick;
59-
60-
public SimpleStringAdapter(List<string> items, Action<string> onClick) { _items = items; _onClick = onClick; }
54+
private List<string> _artistNames;
55+
56+
public BaseViewModelAnd MyViewModel { get; }
57+
public ArtistPickerBottomSheet ArtistPickerBottomSheet { get; }
58+
59+
public ArtistBottomSheetRecyclerViewAdapter(List<string> items
60+
,BaseViewModelAnd vm,
61+
ArtistPickerBottomSheet artistPickerBottomSheet)
62+
{
63+
_artistNames = items;
64+
MyViewModel = vm;
65+
ArtistPickerBottomSheet = artistPickerBottomSheet;
66+
}
6167

62-
public override int ItemCount => _items.Count;
68+
public override int ItemCount => _artistNames.Count;
6369

6470
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
6571
{
66-
var vh = holder as VHolder;
67-
vh.Text.Text = _items[position];
68-
vh.ItemView.Click += (s, e) =>
72+
if (holder is ArtistPickerVHolder songHolder)
6973
{
70-
_onClick(_items[position]);
71-
};
74+
var artist = _artistNames[position];
75+
songHolder.BindData(ArtistPickerBottomSheet, artist);
76+
77+
}
7278
}
7379

7480
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
7581
{
76-
var splitBtn = new MaterialSplitButton(parent.Context);
77-
splitBtn.SetPadding(24, 24, 24, 24);
78-
splitBtn.Click += (s, e) =>
79-
{
80-
var popUp = new PopupMenu(parent.Context, parent);
82+
MaterialCardView? card = UiBuilder.CreateCard(parent.Context);
8183

82-
popUp.Show();
83-
Debug.WriteLine("Clickedd");
84-
};
85-
splitBtn.ContextClick += (s, e) =>
86-
{
87-
Debug.WriteLine("Context Clickedd");
88-
};
84+
var hLL = new LinearLayout (parent.Context);
85+
hLL.Orientation = Android.Widget.Orientation.Horizontal;
8986

90-
var tv = new TextView(parent.Context) { TextSize = 18 };
91-
tv.SetPadding(24, 24, 24, 24);
92-
return new VHolder(tv);
87+
var artistBtn = new MaterialButton(parent.Context);
88+
89+
artistBtn.SetPadding(24, 24, 24, 24);
90+
91+
var TQLChip = new Chip(parent.Context);
92+
TQLChip.SetChipIconResource(Resource.Drawable.searchd);
93+
94+
var FavArtistChip = new Chip(parent.Context);
95+
FavArtistChip.SetChipIconResource(Resource.Drawable.heart);
96+
97+
98+
var ViewChip = new Chip(parent.Context);
99+
ViewChip.SetChipIconResource(Resource.Drawable.eye);
100+
101+
hLL.AddView(artistBtn);
102+
hLL.AddView(TQLChip);
103+
hLL.AddView(FavArtistChip);
104+
hLL.AddView(ViewChip);
105+
card.AddView(hLL);
106+
107+
return new ArtistPickerVHolder(card,artistBtn,TQLChip,FavArtistChip,ViewChip, MyViewModel);
93108
}
94109

95-
class VHolder : RecyclerView.ViewHolder
110+
class ArtistPickerVHolder : RecyclerView.ViewHolder
96111
{
97-
public TextView Text => (TextView)ItemView;
98-
public VHolder(View v) : base(v) { }
112+
public MaterialCardView ContainerView ;
113+
public MaterialButton ArtistBtnView;
114+
115+
BaseViewModelAnd MyViewModel { get; }
116+
117+
public ArtistPickerVHolder(MaterialCardView container, MaterialButton artistBtn, Chip tQLChip, Chip favArtistChip, Chip viewChip, BaseViewModelAnd myViewModel) : base(container)
118+
{
119+
MyViewModel = myViewModel;
120+
121+
ContainerView = container;
122+
ArtistBtnView = artistBtn;
123+
124+
125+
ArtistBtnView.Click += (s, e) =>
126+
{
127+
128+
MyViewModel.SearchSongForSearchResultHolder(TQlStaticMethods.PresetQueries.ByArtist(ArtistName)
129+
);
130+
parent?.Dismiss();
131+
Toast.MakeText(container.Context, $"Selected {ArtistName}", ToastLength.Short)?.Show();
132+
};
133+
}
134+
ArtistPickerBottomSheet? parent;
135+
string? ArtistName;
136+
137+
138+
public void BindData ( ArtistPickerBottomSheet artistPickerBottomSheet, string artist)
139+
{
140+
parent = artistPickerBottomSheet;
141+
ArtistName=artist;
142+
}
99143
}
100144
}
101145
}

0 commit comments

Comments
 (0)