(...);
+}
+-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
+ **[] $VALUES;
+ public *;
+}
+-keep class com.bumptech.glide.load.data.ParcelFileDescriptorRewinder$InternalRewinder {
+ *** rewind();
}
--keep class !android.support.v7.internal.view.menu.**,** {*;}
+# OkHttp
+-keepattributes Signature
+-keepattributes *Annotation*
+-keep interface com.squareup.okhttp3.** { *; }
+-dontwarn com.squareup.okhttp3.**
--dontwarn
--ignorewarnings
+#-dontwarn
+#-ignorewarnings
--keep public class android.support.design.widget.BottomNavigationView { *; }
--keep public class android.support.design.internal.BottomNavigationMenuView { *; }
--keep public class android.support.design.internal.BottomNavigationPresenter { *; }
--keep public class android.support.design.internal.BottomNavigationItemView { *; }
+#Jaudiotagger
+-dontwarn org.jaudiotagger.**
+-dontwarn org.jcodec.**
+-keep class org.jaudiotagger.** { *; }
+-keep class org.jcodec.** { *; }
-#-dontwarn android.support.v8.renderscript.*
-#-keepclassmembers class android.support.v8.renderscript.RenderScript {
-# native *** rsn*(...);
-# native *** n*(...);
-#}
-
-#-keep class org.jaudiotagger.** { *; }
-
-#For cast
--keep class code.name.monkey.retromusic.cast.CastOptionsProvider { *; }
--keep class android.support.** { *; }
--keep class com.google.** { *; }
--keep class java.nio.file.** { *; }
-
--obfuscationdictionary build/obfuscation-dictionary.txt
--classobfuscationdictionary build/class-dictionary.txt
--packageobfuscationdictionary build/package-dictionary.txt
+-keepclassmembers enum * { *; }
+-keepattributes *Annotation*, Signature, Exception
+-keepnames class androidx.navigation.fragment.NavHostFragment
+-keep class * extends androidx.fragment.app.Fragment{}
+-keepnames class * extends android.os.Parcelable
+-keepnames class * extends java.io.Serializable
+-keep class code.name.monkey.retromusic.network.model.** { *; }
+-keep class code.name.monkey.retromusic.model.** { *; }
+-keep class com.google.android.material.bottomsheet.** { *; }
\ No newline at end of file
diff --git a/app/src/debug/res/font/bold.ttf b/app/src/debug/res/font/bold.ttf
new file mode 100644
index 000000000..96619df92
Binary files /dev/null and b/app/src/debug/res/font/bold.ttf differ
diff --git a/app/src/debug/res/font/google_sans_bold.ttf b/app/src/debug/res/font/google_sans_bold.ttf
new file mode 100644
index 000000000..80497666e
Binary files /dev/null and b/app/src/debug/res/font/google_sans_bold.ttf differ
diff --git a/app/src/debug/res/font/google_sans_medium.ttf b/app/src/debug/res/font/google_sans_medium.ttf
new file mode 100644
index 000000000..1543660da
Binary files /dev/null and b/app/src/debug/res/font/google_sans_medium.ttf differ
diff --git a/app/src/debug/res/font/google_sans_regular.ttf b/app/src/debug/res/font/google_sans_regular.ttf
new file mode 100644
index 000000000..ab605f9e2
Binary files /dev/null and b/app/src/debug/res/font/google_sans_regular.ttf differ
diff --git a/app/src/debug/res/font/medium.ttf b/app/src/debug/res/font/medium.ttf
new file mode 100644
index 000000000..fd818d6f5
Binary files /dev/null and b/app/src/debug/res/font/medium.ttf differ
diff --git a/app/src/debug/res/font/regular.ttf b/app/src/debug/res/font/regular.ttf
new file mode 100644
index 000000000..e2c69c3fb
Binary files /dev/null and b/app/src/debug/res/font/regular.ttf differ
diff --git a/app/src/debug/res/font/sans.xml b/app/src/debug/res/font/sans.xml
new file mode 100644
index 000000000..7bbc8513b
--- /dev/null
+++ b/app/src/debug/res/font/sans.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/debug/res/values/bools.xml b/app/src/debug/res/values/bools.xml
new file mode 100644
index 000000000..7d3f0ee62
--- /dev/null
+++ b/app/src/debug/res/values/bools.xml
@@ -0,0 +1,5 @@
+
+
+ true
+ false
+
\ No newline at end of file
diff --git a/app/src/debug/res/values/donottranslate.xml b/app/src/debug/res/values/donottranslate.xml
new file mode 100644
index 000000000..79e559838
--- /dev/null
+++ b/app/src/debug/res/values/donottranslate.xml
@@ -0,0 +1,4 @@
+
+
+ Metro Debug
+
\ No newline at end of file
diff --git a/app/src/debug/res/values/styles.xml b/app/src/debug/res/values/styles.xml
new file mode 100644
index 000000000..f3761b219
--- /dev/null
+++ b/app/src/debug/res/values/styles.xml
@@ -0,0 +1,105 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index defca55c8..14fbaaab7 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,40 +1,57 @@
+ package="code.name.monkey.retromusic"
+ android:installLocation="auto">
-
+
+
+
+
-
-
-
-
+
+
+
+
-
-
+
+
+ android:usesCleartextTraffic="true"
+ tools:ignore="UnusedAttribute">
+ android:exported="true"
+ android:launchMode="singleTop"
+ android:theme="@style/Theme.RetroMusic.SplashScreen">
@@ -45,7 +62,6 @@
-
@@ -105,32 +121,54 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
-
+
-
+
@@ -177,7 +216,7 @@
@@ -190,7 +229,7 @@
@@ -202,7 +241,7 @@
@@ -214,7 +253,7 @@
@@ -226,7 +265,7 @@
@@ -236,13 +275,36 @@
android:name="android.appwidget.provider"
android:resource="@xml/app_widget_card_info" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ android:foregroundServiceType="mediaPlayback"
+ android:label="@string/app_name">
@@ -256,18 +318,33 @@
android:name="com.lge.support.SPLIT_WINDOW"
android:value="true" />
+
+ android:name="com.google.android.gms.car.application"
+ android:resource="@xml/automotive_app_desc" />
+
+
-
-
-
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/assets/contributors.json b/app/src/main/assets/contributors.json
deleted file mode 100644
index 1a743f4d8..000000000
--- a/app/src/main/assets/contributors.json
+++ /dev/null
@@ -1,26 +0,0 @@
-[
- {
- "name": "Hemanth Savarala",
- "summary": "Lead Developer & Designer",
- "link": "https://github.com/h4h13",
- "profile_image": "https://i.imgur.com/AoVs9oj.jpg"
- },
- {
- "name": "Lennart Glamann",
- "summary": "Play Store banner and Images",
- "link": "https://t.me/FlixbusLennart",
- "profile_image": "https://i.imgur.com/Q5Nsx1R.jpg"
- },
- {
- "name": "GameSpeck",
- "summary": "Telegram group maintainer",
- "link": "https://t.me/GameSpeck",
- "profile_image": "https://imgur.com/B15Kb9a.jpg"
- },
- {
- "name": "Milind Goel",
- "summary": "Github & Telegram maintainer",
- "link": "https://t.me/MilindGoel15",
- "profile_image": "https://i.imgur.com/Bz4De21_d.jpg"
- }
-]
\ No newline at end of file
diff --git a/app/src/main/assets/images/daksh.png b/app/src/main/assets/images/daksh.png
new file mode 100644
index 000000000..737f9066c
Binary files /dev/null and b/app/src/main/assets/images/daksh.png differ
diff --git a/app/src/main/assets/images/haythem.jpg b/app/src/main/assets/images/haythem.jpg
new file mode 100644
index 000000000..c74527f1d
Binary files /dev/null and b/app/src/main/assets/images/haythem.jpg differ
diff --git a/app/src/main/assets/images/hemanth.jpg b/app/src/main/assets/images/hemanth.jpg
new file mode 100644
index 000000000..b8f5e7805
Binary files /dev/null and b/app/src/main/assets/images/hemanth.jpg differ
diff --git a/app/src/main/assets/images/lenny.jpg b/app/src/main/assets/images/lenny.jpg
new file mode 100644
index 000000000..7f8025f08
Binary files /dev/null and b/app/src/main/assets/images/lenny.jpg differ
diff --git a/app/src/main/assets/images/milind.png b/app/src/main/assets/images/milind.png
new file mode 100644
index 000000000..bbf9b8278
Binary files /dev/null and b/app/src/main/assets/images/milind.png differ
diff --git a/app/src/main/assets/images/pratham.jpg b/app/src/main/assets/images/pratham.jpg
new file mode 100644
index 000000000..7f05ad9d5
Binary files /dev/null and b/app/src/main/assets/images/pratham.jpg differ
diff --git a/app/src/main/assets/license.html b/app/src/main/assets/license.html
new file mode 100644
index 000000000..2fd8ba5ed
--- /dev/null
+++ b/app/src/main/assets/license.html
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+ Phonograph by
+ Karim Abou Zeid
+AOSP Support Libraries by AOSP contributors
+ Glide by Sam Judd
+ Retrofit by Square team
+
+ OkHttp by Square team
+Koin by Arnaud Giuliani
+ Material Dialogs and Cab
+ by Aidan Michael Follestad
+
+ Material Contextual Action Bar by Aidan Michael Follestad
+ Advanced RecyclerView by Haruki Hasegawa
+Custom Activity on Crash by Eduard Ereza Martínez
+
+NanoHttpd by NanoHttpd Team
+Circular Seekbar by Tankery
+jAudioTagger by Kanedias
+Android Fast Scroll by Zhang Hai
+Image Picker by Dhaval Patel
+Material Intro by Jan Heinrich Reimer
+Slidr by Drew Heavner
+FadingEdgeLayout by bosphere
+KeyboardVisibilityEvent by Yasuhiro SHIMIZU
+android-snowfall by Jetradar Mobile
+Insetter by Chris Banes
+ Icons by Austin Andrews
+ Material Design City Wallpaper
+
+
+
diff --git a/app/src/main/assets/oldindex.html b/app/src/main/assets/oldindex.html
deleted file mode 100644
index a6ce8895f..000000000
--- a/app/src/main/assets/oldindex.html
+++ /dev/null
@@ -1,62 +0,0 @@
-
-
-
-
-
-
-
-
-
- Phonograph by
- Karim Abou Zeid
- Material Dialogs and Cab
- by Aidan Michael Follestad
- AOSP Support Libraries by AOSP contributors
- Glide by Sam Judd
- Retrofit by Square team
-
-
- Material Contextual Action Bar by Aidan Michael Follestad
- OkHttp by Square team
-
- CircleImageView by Henning Dodenhof
-
- MaterialProgressBar by Zhang Hai
- Android In-App Billing v3 Library by
- Henning Dodenhof
- Advanced RecyclerView by Haruki Hasegawa
- Android-ObservableScrollView by Soichiro
- Kashima
- Icons by Austin Andrews
- Material Design City Wallpaper
-
-
-
-
diff --git a/app/src/main/assets/retro-changelog.html b/app/src/main/assets/retro-changelog.html
index 04dcc205e..b6b1c411a 100644
--- a/app/src/main/assets/retro-changelog.html
+++ b/app/src/main/assets/retro-changelog.html
@@ -6,22 +6,23 @@
word-wrap: break-word;
}
- body {
- padding-left: 1rem;
- padding-right: 1rem;
+ div {
+ margin: 20px 10px;
+ padding: 10px;
+ border-radius: 10px;
+ box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.2);
}
h2 {
margin-block-end: 0rem;
margin-block-start: 0rem;
+ display: inline-block;
+ vertical-align: center;
}
li {
font-size: 0.85rem;
- padding-top: 0.5rem;
- padding-left: 0;
- padding-right: 0;
- color: rgba(0, 0, 0, 0.8);
+ padding: 0.5rem 0;
}
ul {
@@ -36,7 +37,6 @@
span {
font-size: 0.7rem;
- line-height: 0.7rem;
}
h5 {
@@ -44,38 +44,423 @@
margin-block-end: 0.5rem;
}
- h3 span {
- border-radius: 0.2rem;
- padding-left: 0.5rem;
- padding-right: 0.5rem;
- padding-top: 0.3rem;
- padding-bottom: 0.3rem;
+ h3 {
+ margin: 10px 0px;
font-size: 1rem;
}
- {style-placeholder}
+ .tag {
+ border-radius: 5px;
+ margin-left: 10px;
+ padding: 5px;
+ display: inline-block;
+ vertical-align: top;
+ }
+
+ {style-placeholder}
-April 30, 2020
-v3.5.110
-Beta version
-
-
- Changed profile form image to icon
- New what's new screen
- Added In-App language changer, where you can select language
-
-
-
- Improved loading of Songs, Albums, Artists, Genres, Playlists
-
-
-*If you face any UI related issues you clear app data and cache, if itsnot working try to
- uninstall and install
- again.
+
+
+
March 30, 2023
+
v6.1.0
+
What's New
+
+ App now targets Android 13, support for Granular media permissions, Photo picker, Per-app language preferences & Predictive back gesture
+
+
Fixed
+
+ Fixed playlist reordering crash
+ Other minor bugs fixes and improvements
+
+
+
+
March 13, 2023
+
v6.0.4
+
What's New
+
+ Minor redesign in Playlist details screen
+ Updated translations
+
+
Fixed
+
+ Fixed file popup menu actions in Folders tab
+ Fixed playlist image loading
+ Fixed blurry album art in Android 13
+ Minor bug fixes and improvements
+
+
+
+
July 10, 2022
+
v6.0.3Beta
+
Fixed
+
+ Migrated icons to Material symbols
+
+
+
+
June 21, 2022
+
v6.0.2Beta
+
Fixed
+
+ Minor bug fixes and improvements
+
+
+
+
June 13, 2022
+
v6.0.1Beta
+
Fixed
+
+ Fixed ChromeCast crash
+ Fixed Slider crashes
+ Fixed storage related crashes on Android 10
+ Fixed CrossFade not working Fade Audio is not working
+
+
+
+
June 7, 2022
+
v6.0.0Beta
+
What's New
+
+ Better Cast
+ Mini player in settings screen
+ Changed Seekbar with Sliders
+ Added NavigationRailView for Landscape
+ Show remaining time in Sleep timer dialog
+
+
Fixed
+
+ Fixed Top/Recent Artists/Albums not updating (Wrong sort order)
+ Fixed all Blacklist related crashes
+ Fix restart button not working in crash activity
+
+
+
+
May 25, 2022
+
v5.8.5
+
What's New
+
+ Display song images along in the artist and album details pages
+ Removed the Internet permissions and all the associated features
+
+
Fixed
+
+ Fixed crashing occurs during changing screen orientation
+
+
+
+
May 13, 2022
+
v5.8.4
+
What's New
+
+ Added a toggle to enable/disable swipe down to dismiss mini player
+
+
Fixed
+
+ Fixed Playback speed and pitch not working when CrossFade is enabled
+ Fixed crash when adding folders to blacklist
+ Fix bugs in MD3 theme
+
+
+
+
May 07, 2022
+
v5.8.3
+
What's New
+
+ Added a new MD3 now playing theme
+ Swipe down to dismiss Mini player
+ Add support for Just Black with Material You
+
+
Fixed
+
+ Fixed sharing of files from SD Card
+ Fix ChromeCast crash and bugs
+ Fix Audio Crossfade
+ Tried to fix incorrect song data in notification
+
+
+
+
April 8, 2022
+
v5.8.0
+
What's New
+
+
Fixed
+
+ Fixed Classic Notification crash
+ Fixed crash when clicking on Playlist in the Search Tab
+ Fixed settings change not reflecting immediately
+ Fixed shuffle
+ Fixed Song duration not visible in Card & Blur card themes
+ Fixed some Album skip styles
+ Minor bug fixes & UI improvements
+
+
+
+
March 13, 2022
+
v5.7.3
+
What's New
+
+ Added adaptive color in Material now playing theme
+ Added an option to share crash report
+ Added options to clear, pause history
+
+
Fixed
+
+ Adapt Wallpaper accent for better readability
+ Optimized search
+ Made sleep timer precise
+
+
+
+
February 13, 2022
+
v5.7.2Beta
+
What's New
+
+ Animated splash screen on Android 12 devices
+
+
Fixed
+
+ Fixed crash when removing song from Playing queue
+ Fixed lyrics editing crash
+ Fixed shuffle button not working
+ Fixed crash on song deletion
+
+
+
+
February 1, 2022
+
v5.7.1Beta
+
What's New
+
+ Added option to disable changing song by swiping anywhere on the now playing screen
+
+
Fixed
+
+ Fixed Playlist save on A11+
+ Fixed Just Black theme
+ Fixed some UI issues
+
+
Improved
+
+ Improvements to search
+
+
+
+
January 25, 2022
+
v5.7.0Beta
+
What's New
+
+ Added Android Auto
+ Added accent color extraction on Android 8.1+ devices
+ Added new Circle widget
+ Added Collapsing appbar to library tabs with an option to switch back to simple appbar
+
+ Added Search tab
+ Added option to use circular play button
+ Added lyrics editing on A11+ devices again
+ Added Long Press to forward, rewind current song
+ Added ability to set Playback speed and pitch
+ Added option to show lyrics over Cover
+ Added option to keep screen on when showing lyrics
+ Added option to switch to Manrope font
+
+
Fixed
+
+ Fixed Gapless Playback
+ Fixed Shuffle FAB going behind Mini Player
+ Fixed crashes on Pre-marshmallow devices
+ Blacklisted songs can't be played after opening from outside the app
+ Fixed various small bugs and some minor improvements
+
+
+
+
January 1, 2021
+
v5.6.1
+
Fixed
+
+ Fixed artist covers not updating and showing album cover images.
+ Fixed FAB's not visible (Shuffle, Save, etc.)
+ Fixed a crash when a Song is deleted in Artist Details
+ Fixed Snowfall effect
+ Fixed empty notification when queue is cleared
+
+
+
+
December 25, 2021
+
v5.6.0Beta
+
What's New
+
+ Added Artwork editing for songs
+ Circle theme has album art now
+ Upgraded tag editor library, we should support reading tags of more formats now e.g.
+ opus.
+
+ Added Snowfall effect
+ Crossfade effect for background when Song is changed for Blur, Blur card themes
+ Album art is hidden when Show lyrics is enabled
+ Added fastscroll in Playlists tab
+ Added Chooser to choose what to restore
+ Hide BottomNavigation when only one tab is selected in Library Categories(This was
+ already there but when changing screens it was getting visible)
+
+
+
Fixed
+
+ Fixed Ringtone crash
+ Fixed blank album cover bug
+ Fixed bottom navigation visible in Playing Queue
+ Fixed lockscreen dragging glitch
+ Fixed incorrect colors when no cover art is available
+ Fixed favorite not updating when song is changed
+ Fixed playlist not getting created & playlist creation crash with same name
+ Fixed a bug in "Plain" Now playing theme where onClick event is consumed by the views
+ behind the bottom sheet
+
+
+
+
+
December 6, 2021
+
v5.4.2Beta
+
Fixed
+
+
+
+
December 1, 2021
+
v5.4.1Beta
+
What's New
+
+ Added file selection from system file picker for restore
+ Added Grid size selection for Playlists
+
+
Improved
+
+ Enable Material You by default on Android 12
+ Reworked Grid Style saving
+ Improved Playlist preview images
+ UI improvements
+
+
Improved
+
+ Fixed File deletion on Android 10
+ Fixed Sleep Timer crash
+ Fixed Bottom Toolbar not clickable in now playing when Shuffle is clicked
+ Fixed Album Artist sort order
+ Fixed a crash when clicking the "Clear All" button in the Blacklist folder selection
+
+ Fixed Continuous crashes on A12 when the song ends
+ Fixed New Music Mix multiple clicks crash
+
+
+
+
November 22, 2021
+
v5.4.0Beta
+
What's New
+
+ Material You
+ Going Edge-to-Edge
+ Added Backup & restore
+
+
Improved
+
+ Improved Animations
+ Improved Crossfade
+
+
+
+
September 06, 2021
+
v5.0.0
+
What's New
+
+ Added ability to Remember last tab
+ Added Whitelisting songs
+ You can now browse SDCard from Folders Tab
+
+
+
+
August 22, 2021
+
v4.4.0Beta
+
What's New
+
+ Added Crossfade
+ Multi-select in Album and Artist Details
+ Albums now show Album Artists instead of artist of first song
+
+
Fixed
+
+ Fixed Playlist Preview Images
+
+
+
+
August 11, 2021
+
v4.2.30Beta
+
What's New
+
+ Revamped Playlist Tab
+ Revamped Genres Tab
+ Added support for embedded Synced Lyrics
+ Added animated icons
+
+
Fixed
+
+ Fixed Language Switching
+ Fixed some reported bugs
+
+
+
+
July 18, 2021
+
v4.2.020Beta
+
What's New
+
+ Added ChromeCast Support
+ Added Lyrics Editor for Normal and Synced Lyrics
+ Added Ripple Animation for Color Theme
+ Added Drag to seek in Tiny Theme
+ Added Playlist Order
+ Added Search Filters
+ Added Audio Fade
+ Synced Lyrics in all Themes
+ Swipe anywhere to change song
+
+
Improved
+
+ Fixed Navigate by Album Artist
+ Changed New Music Mix Actions
+ Improved Animations
+ And some minor bug fixes and improvements
+
+
+
+
October 12, 2020
+
v4.0.10
+
What's New
+
+ Re-built from scratch using MVVM Architecture and JetPack Components
+ New Material Design icon
+ Implemented a custom database for playlists
+ Added new Material Design motions
+ Bug fixes & performance improvements
+ Revamped Home tab UI
+ Android 11 support
+ And more!
+
+
+
+
April 30, 2020
+
v3.5.110Beta
+
What's New
+
+ Changed profile form image to icon
+ New what's new screen
+ Added In-App language changer, where you can select language
+
+
Improved
+
+ Improved loading of Songs, Albums, Artists, Genres, Playlists
+
+
\ No newline at end of file
diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png
index 991844b5e..aa6e4ae9a 100644
Binary files a/app/src/main/ic_launcher-playstore.png and b/app/src/main/ic_launcher-playstore.png differ
diff --git a/app/src/main/ic_launcher-web.png b/app/src/main/ic_launcher-web.png
index ff0f8b9ff..7e7647db5 100644
Binary files a/app/src/main/ic_launcher-web.png and b/app/src/main/ic_launcher-web.png differ
diff --git a/app/src/main/java/code/name/monkey/retromusic/App.kt b/app/src/main/java/code/name/monkey/retromusic/App.kt
index b40633ce8..93dfe4d96 100644
--- a/app/src/main/java/code/name/monkey/retromusic/App.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/App.kt
@@ -1,77 +1,67 @@
/*
- * Copyright (c) 2019 Hemanth Savarala.
+ * Copyright (c) 2020 Hemanth Savarla.
*
* Licensed under the GNU General Public License v3
*
- * This is free software: you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by
- * the Free Software Foundation either version 3 of the License, or (at your option) any later version.
+ * This is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
+ *
*/
-
package code.name.monkey.retromusic
-import android.widget.Toast
-import androidx.multidex.MultiDexApplication
+import android.app.Application
+import androidx.preference.PreferenceManager
+import cat.ereza.customactivityoncrash.config.CaocConfig
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.VersionUtils
+import code.name.monkey.retromusic.activities.ErrorActivity
+import code.name.monkey.retromusic.activities.MainActivity
import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager
-import code.name.monkey.retromusic.dagger.DaggerMusicComponent
-import code.name.monkey.retromusic.dagger.MusicComponent
-import code.name.monkey.retromusic.dagger.module.AppModule
-import com.anjlab.android.iab.v3.BillingProcessor
-import com.anjlab.android.iab.v3.TransactionDetails
+import code.name.monkey.retromusic.helper.WallpaperAccentManager
+import org.koin.android.ext.koin.androidContext
+import org.koin.core.context.startKoin
-class App : MultiDexApplication() {
+class App : Application() {
- lateinit var billingProcessor: BillingProcessor
+ private val wallpaperAccentManager = WallpaperAccentManager(this)
override fun onCreate() {
super.onCreate()
instance = this
- musicComponent = initDagger(this)
+ startKoin {
+ androidContext(this@App)
+ modules(appModules)
+ }
// default theme
if (!ThemeStore.isConfigured(this, 3)) {
ThemeStore.editTheme(this)
- .accentColorRes(R.color.md_deep_purple_A200)
+ .accentColorRes(code.name.monkey.appthemehelper.R.color.md_deep_purple_A200)
.coloredNavigationBar(true)
.commit()
}
+ wallpaperAccentManager.init()
if (VersionUtils.hasNougatMR())
DynamicShortcutManager(this).initDynamicShortcuts()
- // automatically restores purchases
- billingProcessor = BillingProcessor(this, BuildConfig.GOOGLE_PLAY_LICENSING_KEY,
- object : BillingProcessor.IBillingHandler {
- override fun onProductPurchased(productId: String, details: TransactionDetails?) {}
+ // setting Error activity
+ CaocConfig.Builder.create().errorActivity(ErrorActivity::class.java)
+ .restartActivity(MainActivity::class.java).apply()
- override fun onPurchaseHistoryRestored() {
- Toast.makeText(
- this@App,
- R.string.restored_previous_purchase_please_restart,
- Toast.LENGTH_LONG
- ).show()
- }
-
- override fun onBillingError(errorCode: Int, error: Throwable?) {}
-
- override fun onBillingInitialized() {}
- })
+ // Set Default values for now playing preferences
+ // This will reduce startup time for now playing settings fragment as Preference listener of AbsSlidingMusicPanelActivity won't be called
+ PreferenceManager.setDefaultValues(this, R.xml.pref_now_playing_screen, false)
}
- private fun initDagger(app: App): MusicComponent =
- DaggerMusicComponent.builder()
- .appModule(AppModule(app))
- .build()
-
override fun onTerminate() {
super.onTerminate()
- billingProcessor.release()
+ wallpaperAccentManager.release()
}
companion object {
@@ -80,15 +70,5 @@ class App : MultiDexApplication() {
fun getContext(): App {
return instance!!
}
-
- fun isProVersion(): Boolean {
- return BuildConfig.DEBUG || instance?.billingProcessor!!.isPurchased(
- PRO_VERSION_PRODUCT_ID
- )
- }
-
- lateinit var musicComponent: MusicComponent
-
- const val PRO_VERSION_PRODUCT_ID = "pro_version"
}
}
diff --git a/app/src/main/java/code/name/monkey/retromusic/Constants.kt b/app/src/main/java/code/name/monkey/retromusic/Constants.kt
index 79e76a37a..31032f62b 100644
--- a/app/src/main/java/code/name/monkey/retromusic/Constants.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/Constants.kt
@@ -1,59 +1,62 @@
/*
- * Copyright (c) 2019 Hemanth Savarala.
+ * Copyright (c) 2020 Hemanth Savarla.
*
* Licensed under the GNU General Public License v3
*
- * This is free software: you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by
- * the Free Software Foundation either version 3 of the License, or (at your option) any later version.
+ * This is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
+ *
*/
-
package code.name.monkey.retromusic
import android.provider.BaseColumns
import android.provider.MediaStore
object Constants {
-
- const val RATE_ON_GOOGLE_PLAY =
- "https://play.google.com/store/apps/details?id=code.name.monkey.retromusic"
- const val TRANSLATE = "http://monkeycodeapp.oneskyapp.com/collaboration/project?id=238534"
- const val GITHUB_PROJECT = "https://github.com/h4h13/RetroMusicPlayer"
- const val TELEGRAM_CHANGE_LOG = "https://t.me/retromusiclog"
+ const val TRANSLATE = "https://crowdin.com/project/retromusicplayer"
+ const val GITHUB_PROJECT = "https://github.com/MuntashirAkon/Metro"
+ const val TELEGRAM_CHANGE_LOG = "https://t.me/AppManagerChannel"
const val USER_PROFILE = "profile.jpg"
const val USER_BANNER = "banner.jpg"
- const val APP_INSTAGRAM_LINK = "https://www.instagram.com/retromusicapp/"
- const val APP_TELEGRAM_LINK = "https://t.me/retromusicapp/"
- const val APP_TWITTER_LINK = "https://twitter.com/retromusicapp"
- const val FAQ_LINK = "https://github.com/h4h13/RetroMusicPlayer/blob/master/FAQ.md"
- const val PINTEREST = "https://in.pinterest.com/retromusicapp/"
+ const val FAQ_LINK = "https://github.com/MuntashirAkon/Metro/blob/master/FAQ.md"
const val IS_MUSIC =
MediaStore.Audio.AudioColumns.IS_MUSIC + "=1" + " AND " + MediaStore.Audio.AudioColumns.TITLE + " != ''"
+ const val DATA = "_data"
+
+ @Suppress("Deprecation")
val baseProjection = arrayOf(
BaseColumns._ID, // 0
MediaStore.Audio.AudioColumns.TITLE, // 1
MediaStore.Audio.AudioColumns.TRACK, // 2
MediaStore.Audio.AudioColumns.YEAR, // 3
MediaStore.Audio.AudioColumns.DURATION, // 4
- MediaStore.Audio.AudioColumns.DATA, // 5
+ DATA, // 5
MediaStore.Audio.AudioColumns.DATE_MODIFIED, // 6
MediaStore.Audio.AudioColumns.ALBUM_ID, // 7
MediaStore.Audio.AudioColumns.ALBUM, // 8
MediaStore.Audio.AudioColumns.ARTIST_ID, // 9
- MediaStore.Audio.AudioColumns.ARTIST,// 10
- MediaStore.Audio.AudioColumns.COMPOSER// 11
+ MediaStore.Audio.AudioColumns.ARTIST, // 10
+ MediaStore.Audio.AudioColumns.COMPOSER, // 11
+ ALBUM_ARTIST // 12
)
const val NUMBER_OF_TOP_TRACKS = 99
}
+const val EXTRA_PLAYLIST_TYPE = "type"
+const val EXTRA_GENRE = "extra_genre"
+const val EXTRA_PLAYLIST = "extra_playlist"
+const val EXTRA_PLAYLIST_ID = "extra_playlist_id"
+const val EXTRA_ALBUM_ID = "extra_album_id"
+const val EXTRA_ARTIST_ID = "extra_artist_id"
const val EXTRA_SONG = "extra_songs"
-const val EXTRA_PLAYLIST = "extra_list"
+const val EXTRA_PLAYLISTS = "extra_playlists"
const val LIBRARY_CATEGORIES = "library_categories"
const val EXTRA_SONG_INFO = "extra_song_info"
const val DESATURATED_COLOR = "desaturated_color"
@@ -64,29 +67,27 @@ const val NOW_PLAYING_SCREEN_ID = "now_playing_screen_id"
const val CAROUSEL_EFFECT = "carousel_effect"
const val COLORED_NOTIFICATION = "colored_notification"
const val CLASSIC_NOTIFICATION = "classic_notification"
-const val GAPLESS_PLAYBACK = "gapless_playback"
-const val ALBUM_ART_ON_LOCKSCREEN = "album_art_on_lockscreen"
+const val GAP_LESS_PLAYBACK = "gapless_playback"
+const val ALBUM_ART_ON_LOCK_SCREEN = "album_art_on_lock_screen"
const val BLURRED_ALBUM_ART = "blurred_album_art"
const val NEW_BLUR_AMOUNT = "new_blur_amount"
const val TOGGLE_HEADSET = "toggle_headset"
const val GENERAL_THEME = "general_theme"
+const val ACCENT_COLOR = "accent_color"
+const val SHOULD_COLOR_APP_SHORTCUTS = "should_color_app_shortcuts"
const val CIRCULAR_ALBUM_ART = "circular_album_art"
const val USER_NAME = "user_name"
const val TOGGLE_FULL_SCREEN = "toggle_full_screen"
const val TOGGLE_VOLUME = "toggle_volume"
-const val ROUND_CORNERS = "corner_window"
-const val TOGGLE_GENRE = "toggle_genre"
-const val PROFILE_IMAGE_PATH = "profile_image_path"
-const val BANNER_IMAGE_PATH = "banner_image_path"
const val ADAPTIVE_COLOR_APP = "adaptive_color_app"
-const val TOGGLE_SEPARATE_LINE = "toggle_separate_line"
const val HOME_ARTIST_GRID_STYLE = "home_artist_grid_style"
+const val HOME_ALBUM_GRID_STYLE = "home_album_grid_style"
const val TOGGLE_ADD_CONTROLS = "toggle_add_controls"
const val ALBUM_COVER_STYLE = "album_cover_style_id"
const val ALBUM_COVER_TRANSFORM = "album_cover_transform"
const val TAB_TEXT_MODE = "tab_text_mode"
const val LANGUAGE_NAME = "language_name"
-const val DIALOG_CORNER = "dialog_corner"
+const val LOCALE_AUTO_STORE_ENABLED = "locale_auto_store_enabled"
const val SLEEP_TIMER_FINISH_SONG = "sleep_timer_finish_song"
const val ALBUM_GRID_STYLE = "album_grid_style_home"
const val ARTIST_GRID_STYLE = "artist_grid_style_home"
@@ -94,12 +95,12 @@ const val SAF_SDCARD_URI = "saf_sdcard_uri"
const val SONG_SORT_ORDER = "song_sort_order"
const val SONG_GRID_SIZE = "song_grid_size"
const val GENRE_SORT_ORDER = "genre_sort_order"
-const val LAST_PAGE = "last_start_page"
const val BLUETOOTH_PLAYBACK = "bluetooth_playback"
const val INITIALIZED_BLACKLIST = "initialized_blacklist"
const val ARTIST_SORT_ORDER = "artist_sort_order"
const val ARTIST_ALBUM_SORT_ORDER = "artist_album_sort_order"
const val ALBUM_SORT_ORDER = "album_sort_order"
+const val PLAYLIST_SORT_ORDER = "playlist_sort_order"
const val ALBUM_SONG_SORT_ORDER = "album_song_sort_order"
const val ARTIST_SONG_SORT_ORDER = "artist_song_sort_order"
const val ALBUM_GRID_SIZE = "album_grid_size"
@@ -107,21 +108,47 @@ const val ALBUM_GRID_SIZE_LAND = "album_grid_size_land"
const val SONG_GRID_SIZE_LAND = "song_grid_size_land"
const val ARTIST_GRID_SIZE = "artist_grid_size"
const val ARTIST_GRID_SIZE_LAND = "artist_grid_size_land"
+const val PLAYLIST_GRID_SIZE = "playlist_grid_size"
+const val PLAYLIST_GRID_SIZE_LAND = "playlist_grid_size_land"
const val COLORED_APP_SHORTCUTS = "colored_app_shortcuts"
-const val AUDIO_DUCKING = "audio_ducking"
const val LAST_ADDED_CUTOFF = "last_added_interval"
const val LAST_SLEEP_TIMER_VALUE = "last_sleep_timer_value"
const val NEXT_SLEEP_TIMER_ELAPSED_REALTIME = "next_sleep_timer_elapsed_real_time"
const val IGNORE_MEDIA_STORE_ARTWORK = "ignore_media_store_artwork"
const val LAST_CHANGELOG_VERSION = "last_changelog_version"
-const val AUTO_DOWNLOAD_IMAGES_POLICY = "auto_download_images_policy"
const val START_DIRECTORY = "start_directory"
+const val RECENTLY_PLAYED_CUTOFF = "recently_played_interval"
const val LOCK_SCREEN = "lock_screen"
+const val ALBUM_ARTISTS_ONLY = "album_artists_only"
+const val ALBUM_ARTIST = "album_artist"
const val ALBUM_DETAIL_SONG_SORT_ORDER = "album_detail_song_sort_order"
+const val ARTIST_DETAIL_SONG_SORT_ORDER = "artist_detail_song_sort_order"
const val LYRICS_OPTIONS = "lyrics_tab_position"
const val CHOOSE_EQUALIZER = "choose_equalizer"
-const val TOGGLE_SHUFFLE = "toggle_shuffle"
+const val EQUALIZER = "equalizer"
const val SONG_GRID_STYLE = "song_grid_style"
const val PAUSE_ON_ZERO_VOLUME = "pause_on_zero_volume"
const val FILTER_SONG = "filter_song"
-const val EXPAND_NOW_PLAYING_PANEL = "expand_now_playing_panel"
\ No newline at end of file
+const val EXPAND_NOW_PLAYING_PANEL = "expand_now_playing_panel"
+const val EXTRA_ARTIST_NAME = "extra_artist_name"
+const val TOGGLE_SUGGESTIONS = "toggle_suggestions"
+const val AUDIO_FADE_DURATION = "audio_fade_duration"
+const val CROSS_FADE_DURATION = "cross_fade_duration"
+const val SHOW_LYRICS = "show_lyrics"
+const val REMEMBER_LAST_TAB = "remember_last_tab"
+const val LAST_USED_TAB = "last_used_tab"
+const val WHITELIST_MUSIC = "whitelist_music"
+const val MATERIAL_YOU = "material_you"
+const val SNOWFALL = "snowfall"
+const val LYRICS_TYPE = "lyrics_type"
+const val PLAYBACK_SPEED = "playback_speed"
+const val PLAYBACK_PITCH = "playback_pitch"
+const val CUSTOM_FONT = "custom_font"
+const val APPBAR_MODE = "appbar_mode"
+const val WALLPAPER_ACCENT = "wallpaper_accent"
+const val SCREEN_ON_LYRICS = "screen_on_lyrics"
+const val CIRCLE_PLAY_BUTTON = "circle_play_button"
+const val SWIPE_ANYWHERE_NOW_PLAYING = "swipe_anywhere_now_playing"
+const val PAUSE_HISTORY = "pause_history"
+const val MANAGE_AUDIO_FOCUS = "manage_audio_focus"
+const val SWIPE_DOWN_DISMISS = "swipe_to_dismiss"
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/HomeSection.kt b/app/src/main/java/code/name/monkey/retromusic/HomeSection.kt
new file mode 100644
index 000000000..4f1273a03
--- /dev/null
+++ b/app/src/main/java/code/name/monkey/retromusic/HomeSection.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2020 Hemanth Savarla.
+ *
+ * Licensed under the GNU General Public License v3
+ *
+ * This is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ */
+package code.name.monkey.retromusic
+
+import androidx.annotation.IntDef
+
+@IntDef(
+ RECENT_ALBUMS,
+ TOP_ALBUMS,
+ RECENT_ARTISTS,
+ TOP_ARTISTS,
+ SUGGESTIONS,
+ FAVOURITES,
+ GENRES,
+ PLAYLISTS
+)
+@Retention(AnnotationRetention.SOURCE)
+annotation class HomeSection
+
+const val RECENT_ALBUMS = 3
+const val TOP_ALBUMS = 1
+const val RECENT_ARTISTS = 2
+const val TOP_ARTISTS = 0
+const val SUGGESTIONS = 5
+const val FAVOURITES = 4
+const val GENRES = 6
+const val PLAYLISTS = 7
+const val HISTORY_PLAYLIST = 8
+const val LAST_ADDED_PLAYLIST = 9
+const val TOP_PLAYED_PLAYLIST = 10
diff --git a/app/src/main/java/code/name/monkey/retromusic/LanguageContextWrapper.java b/app/src/main/java/code/name/monkey/retromusic/LanguageContextWrapper.java
deleted file mode 100644
index 36f7f5654..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/LanguageContextWrapper.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package code.name.monkey.retromusic;
-
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.os.LocaleList;
-
-import java.util.Locale;
-
-import code.name.monkey.appthemehelper.util.VersionUtils;
-
-public class LanguageContextWrapper extends ContextWrapper {
-
- public LanguageContextWrapper(Context base) {
- super(base);
- }
-
- public static LanguageContextWrapper wrap(Context context, Locale newLocale) {
- Resources res = context.getResources();
- Configuration configuration = res.getConfiguration();
-
- if (VersionUtils.INSTANCE.hasNougatMR()) {
- configuration.setLocale(newLocale);
-
- LocaleList localeList = new LocaleList(newLocale);
- LocaleList.setDefault(localeList);
- configuration.setLocales(localeList);
-
- context = context.createConfigurationContext(configuration);
-
- } else if (VersionUtils.INSTANCE.hasLollipop()) {
- configuration.setLocale(newLocale);
- context = context.createConfigurationContext(configuration);
-
- } else {
- configuration.locale = newLocale;
- res.updateConfiguration(configuration, res.getDisplayMetrics());
- }
-
- return new LanguageContextWrapper(context);
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/MainModule.kt b/app/src/main/java/code/name/monkey/retromusic/MainModule.kt
new file mode 100644
index 000000000..d88f8a760
--- /dev/null
+++ b/app/src/main/java/code/name/monkey/retromusic/MainModule.kt
@@ -0,0 +1,156 @@
+package code.name.monkey.retromusic
+
+import androidx.room.Room
+import code.name.monkey.retromusic.auto.AutoMusicProvider
+import code.name.monkey.retromusic.db.MIGRATION_23_24
+import code.name.monkey.retromusic.db.RetroDatabase
+import code.name.monkey.retromusic.fragments.LibraryViewModel
+import code.name.monkey.retromusic.fragments.albums.AlbumDetailsViewModel
+import code.name.monkey.retromusic.fragments.artists.ArtistDetailsViewModel
+import code.name.monkey.retromusic.fragments.genres.GenreDetailsViewModel
+import code.name.monkey.retromusic.fragments.playlists.PlaylistDetailsViewModel
+import code.name.monkey.retromusic.model.Genre
+import code.name.monkey.retromusic.repository.*
+import org.koin.android.ext.koin.androidContext
+import org.koin.androidx.viewmodel.dsl.viewModel
+import org.koin.dsl.bind
+import org.koin.dsl.module
+
+private val roomModule = module {
+
+ single {
+ Room.databaseBuilder(androidContext(), RetroDatabase::class.java, "playlist.db")
+ .addMigrations(MIGRATION_23_24)
+ .build()
+ }
+
+ factory {
+ get().playlistDao()
+ }
+
+ factory {
+ get().playCountDao()
+ }
+
+ factory {
+ get().historyDao()
+ }
+
+ single {
+ RealRoomRepository(get(), get(), get())
+ } bind RoomRepository::class
+}
+private val autoModule = module {
+ single {
+ AutoMusicProvider(
+ androidContext(),
+ get(),
+ get(),
+ get(),
+ get(),
+ get(),
+ get()
+ )
+ }
+}
+private val mainModule = module {
+ single {
+ androidContext().contentResolver
+ }
+}
+private val dataModule = module {
+ single {
+ RealRepository(
+ get(),
+ get(),
+ get(),
+ get(),
+ get(),
+ get(),
+ get(),
+ get(),
+ get(),
+ get(),
+ )
+ } bind Repository::class
+
+ single {
+ RealSongRepository(get())
+ } bind SongRepository::class
+
+ single {
+ RealGenreRepository(get(), get())
+ } bind GenreRepository::class
+
+ single {
+ RealAlbumRepository(get())
+ } bind AlbumRepository::class
+
+ single {
+ RealArtistRepository(get(), get())
+ } bind ArtistRepository::class
+
+ single {
+ RealPlaylistRepository(get())
+ } bind PlaylistRepository::class
+
+ single {
+ RealTopPlayedRepository(get(), get(), get(), get())
+ } bind TopPlayedRepository::class
+
+ single {
+ RealLastAddedRepository(
+ get(),
+ get(),
+ get()
+ )
+ } bind LastAddedRepository::class
+
+ single {
+ RealSearchRepository(
+ get(),
+ get(),
+ get(),
+ get(),
+ get()
+ )
+ }
+}
+
+private val viewModules = module {
+
+ viewModel {
+ LibraryViewModel(get())
+ }
+
+ viewModel { (albumId: Long) ->
+ AlbumDetailsViewModel(
+ get(),
+ albumId
+ )
+ }
+
+ viewModel { (artistId: Long?, artistName: String?) ->
+ ArtistDetailsViewModel(
+ get(),
+ artistId,
+ artistName
+ )
+ }
+
+ viewModel { (playlistId: Long) ->
+ PlaylistDetailsViewModel(
+ get(),
+ playlistId
+ )
+ }
+
+ viewModel { (genre: Genre) ->
+ GenreDetailsViewModel(
+ get(),
+ genre
+ )
+ }
+}
+
+val appModules = listOf(mainModule, dataModule, autoModule, viewModules, roomModule)
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/Result.kt b/app/src/main/java/code/name/monkey/retromusic/Result.kt
deleted file mode 100644
index 64b638a6e..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/Result.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2019 Hemanth Savarala.
- *
- * Licensed under the GNU General Public License v3
- *
- * This is free software: you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by
- * the Free Software Foundation either version 3 of the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- */
-
-package code.name.monkey.retromusic
-
-/**
- * Created by hemanths on 2019-10-23.
- */
-
-sealed class Result {
-
- class Success(val data: T) : Result()
-
- class Error(val exception: Throwable) : Result()
-}
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/RetroBottomSheetBehavior.java b/app/src/main/java/code/name/monkey/retromusic/RetroBottomSheetBehavior.java
deleted file mode 100644
index abff707a4..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/RetroBottomSheetBehavior.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package code.name.monkey.retromusic;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.view.View;
-
-import androidx.coordinatorlayout.widget.CoordinatorLayout;
-
-import com.google.android.material.bottomsheet.BottomSheetBehavior;
-
-import org.jetbrains.annotations.NotNull;
-
-
-public class RetroBottomSheetBehavior extends BottomSheetBehavior {
-
- private static final String TAG = "RetroBottomSheetBehavior";
-
- private boolean allowDragging = true;
-
- public RetroBottomSheetBehavior() {
- }
-
- public RetroBottomSheetBehavior(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public void setAllowDragging(boolean allowDragging) {
- this.allowDragging = allowDragging;
- }
-
- @Override
- public boolean onInterceptTouchEvent(@NotNull CoordinatorLayout parent, @NotNull V child, @NotNull MotionEvent event) {
- if (!allowDragging) {
- return false;
- }
- return super.onInterceptTouchEvent(parent, child, event);
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/AboutActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/AboutActivity.kt
deleted file mode 100644
index 58650582e..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/activities/AboutActivity.kt
+++ /dev/null
@@ -1,148 +0,0 @@
-package code.name.monkey.retromusic.activities
-
-import android.content.Intent
-import android.content.pm.PackageManager
-import android.net.Uri
-import android.os.Bundle
-import android.view.MenuItem
-import android.view.View
-import androidx.core.app.ShareCompat
-import androidx.recyclerview.widget.DefaultItemAnimator
-import androidx.recyclerview.widget.LinearLayoutManager
-import code.name.monkey.retromusic.App
-import code.name.monkey.retromusic.Constants.APP_INSTAGRAM_LINK
-import code.name.monkey.retromusic.Constants.APP_TELEGRAM_LINK
-import code.name.monkey.retromusic.Constants.APP_TWITTER_LINK
-import code.name.monkey.retromusic.Constants.FAQ_LINK
-import code.name.monkey.retromusic.Constants.GITHUB_PROJECT
-import code.name.monkey.retromusic.Constants.PINTEREST
-import code.name.monkey.retromusic.Constants.RATE_ON_GOOGLE_PLAY
-import code.name.monkey.retromusic.Constants.TELEGRAM_CHANGE_LOG
-import code.name.monkey.retromusic.Constants.TRANSLATE
-import code.name.monkey.retromusic.R
-import code.name.monkey.retromusic.activities.base.AbsBaseActivity
-import code.name.monkey.retromusic.adapter.ContributorAdapter
-import code.name.monkey.retromusic.extensions.applyToolbar
-import code.name.monkey.retromusic.model.Contributor
-import code.name.monkey.retromusic.util.NavigationUtil
-import com.google.gson.Gson
-import com.google.gson.reflect.TypeToken
-import kotlinx.android.synthetic.main.activity_about.*
-import kotlinx.android.synthetic.main.card_credit.*
-import kotlinx.android.synthetic.main.card_other.*
-import kotlinx.android.synthetic.main.card_retro_info.*
-import kotlinx.android.synthetic.main.card_social.*
-import java.io.IOException
-import java.nio.charset.StandardCharsets
-
-class AboutActivity : AbsBaseActivity(), View.OnClickListener {
-
- private val contributorsJson: String?
- get() {
- val json: String
- try {
- val inputStream = assets.open("contributors.json")
- val size = inputStream.available()
- val buffer = ByteArray(size)
- inputStream.read(buffer)
- inputStream.close()
- json = String(buffer, StandardCharsets.UTF_8)
- } catch (ex: IOException) {
- ex.printStackTrace()
- return null
- }
- return json
- }
-
- override fun onCreate(savedInstanceState: Bundle?) {
- setDrawUnderStatusBar()
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_about)
- setStatusbarColorAuto()
- setNavigationbarColorAuto()
- setLightNavigationBar(true)
-
- applyToolbar(toolbar)
- version.setSummary(getAppVersion())
- setUpView()
- loadContributors()
- }
-
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- if (item.itemId == android.R.id.home) {
- onBackPressed()
- return true
- }
- return super.onOptionsItemSelected(item)
- }
-
- private fun openUrl(url: String) {
- val i = Intent(Intent.ACTION_VIEW)
- i.data = Uri.parse(url)
- i.flags = Intent.FLAG_ACTIVITY_NEW_TASK
- startActivity(i)
- }
-
- private fun setUpView() {
- appGithub.setOnClickListener(this)
- faqLink.setOnClickListener(this)
- telegramLink.setOnClickListener(this)
- appRate.setOnClickListener(this)
- appTranslation.setOnClickListener(this)
- appShare.setOnClickListener(this)
- donateLink.setOnClickListener(this)
- instagramLink.setOnClickListener(this)
- twitterLink.setOnClickListener(this)
- changelog.setOnClickListener(this)
- openSource.setOnClickListener(this)
- pinterestLink.setOnClickListener(this)
- bugReportLink.setOnClickListener(this)
- }
-
- override fun onClick(view: View) {
- when (view.id) {
- R.id.pinterestLink -> openUrl(PINTEREST)
- R.id.faqLink -> openUrl(FAQ_LINK)
- R.id.telegramLink -> openUrl(APP_TELEGRAM_LINK)
- R.id.appGithub -> openUrl(GITHUB_PROJECT)
- R.id.appTranslation -> openUrl(TRANSLATE)
- R.id.appRate -> openUrl(RATE_ON_GOOGLE_PLAY)
- R.id.appShare -> shareApp()
- R.id.donateLink -> NavigationUtil.goToSupportDevelopment(this)
- R.id.instagramLink -> openUrl(APP_INSTAGRAM_LINK)
- R.id.twitterLink -> openUrl(APP_TWITTER_LINK)
- R.id.changelog -> openUrl(TELEGRAM_CHANGE_LOG)
- R.id.openSource -> NavigationUtil.goToOpenSource(this)
- R.id.bugReportLink -> NavigationUtil.bugReport(this)
- }
- }
-
- private fun getAppVersion(): String {
- return try {
- val isPro = if (App.isProVersion()) "Pro" else "Free"
- val packageInfo = packageManager.getPackageInfo(packageName, 0)
- "${packageInfo.versionName} $isPro"
- } catch (e: PackageManager.NameNotFoundException) {
- e.printStackTrace()
- "0.0.0"
- }
- }
-
- private fun shareApp() {
- ShareCompat.IntentBuilder.from(this).setType("text/plain")
- .setChooserTitle(R.string.share_app)
- .setText(String.format(getString(R.string.app_share), packageName)).startChooser()
- }
-
- private fun loadContributors() {
- val type = object : TypeToken>() {
-
- }.type
- val contributors = Gson().fromJson>(contributorsJson, type)
-
- val contributorAdapter = ContributorAdapter(contributors)
- recyclerView.layoutManager = LinearLayoutManager(this)
- recyclerView.itemAnimator = DefaultItemAnimator()
- recyclerView.adapter = contributorAdapter
- }
-}
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/DriveModeActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/DriveModeActivity.kt
index 3602d86f4..af3890d22 100644
--- a/app/src/main/java/code/name/monkey/retromusic/activities/DriveModeActivity.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/activities/DriveModeActivity.kt
@@ -1,46 +1,48 @@
/*
- * Copyright (c) 2020 Hemanth Savarala.
+ * Copyright (c) 2020 Hemanth Savarla.
*
* Licensed under the GNU General Public License v3
*
- * This is free software: you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by
- * the Free Software Foundation either version 3 of the License, or (at your option) any later version.
+ * This is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
+ *
*/
-
package code.name.monkey.retromusic.activities
-import android.animation.ObjectAnimator
+import android.content.Intent
import android.graphics.Color
import android.graphics.PorterDuff
import android.os.Bundle
-import android.view.animation.LinearInterpolator
-import android.widget.SeekBar
-import code.name.monkey.appthemehelper.ThemeStore
+import androidx.lifecycle.lifecycleScope
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.activities.base.AbsMusicServiceActivity
-import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
+import code.name.monkey.retromusic.databinding.ActivityDriveModeBinding
+import code.name.monkey.retromusic.db.toSongEntity
+import code.name.monkey.retromusic.extensions.accentColor
+import code.name.monkey.retromusic.extensions.drawAboveSystemBars
import code.name.monkey.retromusic.glide.BlurTransformation
-import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
-import code.name.monkey.retromusic.glide.SongGlideRequest
+import code.name.monkey.retromusic.glide.RetroGlideExtension
+import code.name.monkey.retromusic.glide.RetroGlideExtension.songCoverOptions
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper.Callback
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
-import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
+import code.name.monkey.retromusic.model.Song
+import code.name.monkey.retromusic.repository.RealRepository
import code.name.monkey.retromusic.service.MusicService
import code.name.monkey.retromusic.util.MusicUtil
-import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.bumptech.glide.Glide
-import kotlinx.android.synthetic.main.activity_drive_mode.*
-import kotlinx.coroutines.CoroutineScope
+import com.google.android.material.slider.Slider
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
+import org.koin.android.ext.android.inject
+
/**
* Created by hemanths on 2020-02-02.
@@ -48,21 +50,24 @@ import kotlinx.coroutines.withContext
class DriveModeActivity : AbsMusicServiceActivity(), Callback {
+ private lateinit var binding: ActivityDriveModeBinding
private var lastPlaybackControlsColor: Int = Color.GRAY
private var lastDisabledPlaybackControlsColor: Int = Color.GRAY
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
+ private val repository: RealRepository by inject()
override fun onCreate(savedInstanceState: Bundle?) {
- setDrawUnderStatusBar()
super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_drive_mode)
+ binding = ActivityDriveModeBinding.inflate(layoutInflater)
+ setContentView(binding.root)
setUpMusicControllers()
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
- lastPlaybackControlsColor = ThemeStore.accentColor(this)
- close.setOnClickListener {
- onBackPressed()
+ lastPlaybackControlsColor = accentColor()
+ binding.close.setOnClickListener {
+ onBackPressedDispatcher.onBackPressed()
}
+ binding.repeatButton.drawAboveSystemBars()
}
private fun setUpMusicControllers() {
@@ -75,36 +80,45 @@ class DriveModeActivity : AbsMusicServiceActivity(), Callback {
}
private fun setupFavouriteToggle() {
- songFavourite.setOnClickListener {
- MusicUtil.toggleFavorite(
- this@DriveModeActivity,
- MusicPlayerRemote.currentSong
- )
+ binding.songFavourite.setOnClickListener {
+ toggleFavorite(MusicPlayerRemote.currentSong)
}
}
- private fun toggleFavourite() {
- CoroutineScope(Dispatchers.IO).launch {
- val isFavourite =
- MusicUtil.isFavorite(this@DriveModeActivity, MusicPlayerRemote.currentSong)
+ private fun toggleFavorite(song: Song) {
+ lifecycleScope.launch(Dispatchers.IO) {
+ val playlist = repository.favoritePlaylist()
+ val songEntity = song.toSongEntity(playlist.playListId)
+ val isFavorite = repository.isSongFavorite(song.id)
+ if (isFavorite) {
+ repository.removeSongFromPlaylist(songEntity)
+ } else {
+ repository.insertSongs(listOf(song.toSongEntity(playlist.playListId)))
+ }
+ sendBroadcast(Intent(MusicService.FAVORITE_STATE_CHANGED))
+ }
+ }
+
+ private fun updateFavorite() {
+ lifecycleScope.launch(Dispatchers.IO) {
+ val isFavorite: Boolean =
+ repository.isSongFavorite(MusicPlayerRemote.currentSong.id)
withContext(Dispatchers.Main) {
- songFavourite.setImageResource(if (isFavourite) R.drawable.ic_favorite_white_24dp else R.drawable.ic_favorite_border_white_24dp)
+ binding.songFavourite.setImageResource(if (isFavorite) R.drawable.ic_favorite else R.drawable.ic_favorite_border)
}
}
}
private fun setUpProgressSlider() {
- progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
- override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
- if (fromUser) {
- MusicPlayerRemote.seekTo(progress)
- onUpdateProgressViews(
- MusicPlayerRemote.songProgressMillis,
- MusicPlayerRemote.songDurationMillis
- )
- }
+ binding.progressSlider.addOnChangeListener { _: Slider, progress: Float, fromUser: Boolean ->
+ if (fromUser) {
+ MusicPlayerRemote.seekTo(progress.toInt())
+ onUpdateProgressViews(
+ MusicPlayerRemote.songProgressMillis,
+ MusicPlayerRemote.songDurationMillis
+ )
}
- })
+ }
}
override fun onPause() {
@@ -118,21 +132,20 @@ class DriveModeActivity : AbsMusicServiceActivity(), Callback {
}
private fun setUpPrevNext() {
-
- nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
- previousButton.setOnClickListener { MusicPlayerRemote.back() }
+ binding.nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
+ binding.previousButton.setOnClickListener { MusicPlayerRemote.back() }
}
private fun setUpShuffleButton() {
- shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
+ binding.shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
}
private fun setUpRepeatButton() {
- repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
+ binding.repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
}
private fun setUpPlayPauseFab() {
- playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
+ binding.playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
}
override fun onRepeatModeChanged() {
@@ -156,24 +169,25 @@ class DriveModeActivity : AbsMusicServiceActivity(), Callback {
updateSong()
updateRepeatState()
updateShuffleState()
- toggleFavourite()
+ updateFavorite()
}
private fun updatePlayPauseDrawableState() {
if (MusicPlayerRemote.isPlaying) {
- playPauseButton.setImageResource(R.drawable.ic_pause_white_24dp)
+ binding.playPauseButton.setImageResource(R.drawable.ic_pause)
} else {
- playPauseButton.setImageResource(R.drawable.ic_play_arrow_white_24dp)
+ binding.playPauseButton.setImageResource(R.drawable.ic_play_arrow)
}
}
fun updateShuffleState() {
when (MusicPlayerRemote.shuffleMode) {
- MusicService.SHUFFLE_MODE_SHUFFLE -> shuffleButton.setColorFilter(
+ MusicService.SHUFFLE_MODE_SHUFFLE -> binding.shuffleButton.setColorFilter(
lastPlaybackControlsColor,
PorterDuff.Mode.SRC_IN
)
- else -> shuffleButton.setColorFilter(
+
+ else -> binding.shuffleButton.setColorFilter(
lastDisabledPlaybackControlsColor,
PorterDuff.Mode.SRC_IN
)
@@ -183,19 +197,27 @@ class DriveModeActivity : AbsMusicServiceActivity(), Callback {
private fun updateRepeatState() {
when (MusicPlayerRemote.repeatMode) {
MusicService.REPEAT_MODE_NONE -> {
- repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
- repeatButton.setColorFilter(
+ binding.repeatButton.setImageResource(R.drawable.ic_repeat)
+ binding.repeatButton.setColorFilter(
lastDisabledPlaybackControlsColor,
PorterDuff.Mode.SRC_IN
)
}
+
MusicService.REPEAT_MODE_ALL -> {
- repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
- repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
+ binding.repeatButton.setImageResource(R.drawable.ic_repeat)
+ binding.repeatButton.setColorFilter(
+ lastPlaybackControlsColor,
+ PorterDuff.Mode.SRC_IN
+ )
}
+
MusicService.REPEAT_MODE_THIS -> {
- repeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp)
- repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
+ binding.repeatButton.setImageResource(R.drawable.ic_repeat_one)
+ binding.repeatButton.setColorFilter(
+ lastPlaybackControlsColor,
+ PorterDuff.Mode.SRC_IN
+ )
}
}
}
@@ -203,35 +225,34 @@ class DriveModeActivity : AbsMusicServiceActivity(), Callback {
override fun onPlayingMetaChanged() {
super.onPlayingMetaChanged()
updateSong()
- toggleFavourite()
+ updateFavorite()
+ }
+
+ override fun onFavoriteStateChanged() {
+ super.onFavoriteStateChanged()
+ updateFavorite()
}
private fun updateSong() {
val song = MusicPlayerRemote.currentSong
- songTitle.text = song.title
- songText.text = song.artistName
+ binding.songTitle.text = song.title
+ binding.songText.text = song.artistName
- SongGlideRequest.Builder.from(Glide.with(this), song)
- .checkIgnoreMediaStore(this)
- .generatePalette(this)
- .build()
+ Glide.with(this)
+ .load(RetroGlideExtension.getSongModel(song))
+ .songCoverOptions(song)
.transform(BlurTransformation.Builder(this).build())
- .into(object : RetroMusicColoredTarget(image) {
- override fun onColorReady(color: MediaNotificationProcessor) {
- }
- })
+ .into(binding.image)
}
override fun onUpdateProgressViews(progress: Int, total: Int) {
- progressSlider.max = total
+ binding.progressSlider.run {
+ valueTo = total.toFloat()
+ value = progress.toFloat().coerceIn(valueFrom, valueTo)
+ }
- val animator = ObjectAnimator.ofInt(progressSlider, "progress", progress)
- animator.duration = AbsPlayerControlsFragment.SLIDER_ANIMATION_TIME
- animator.interpolator = LinearInterpolator()
- animator.start()
-
- songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
- songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
+ binding.songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
+ binding.songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/ErrorActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/ErrorActivity.kt
new file mode 100644
index 000000000..6823b80f8
--- /dev/null
+++ b/app/src/main/java/code/name/monkey/retromusic/activities/ErrorActivity.kt
@@ -0,0 +1,80 @@
+package code.name.monkey.retromusic.activities
+
+import android.os.Bundle
+import android.widget.Button
+import android.widget.ImageView
+import androidx.appcompat.app.AppCompatActivity
+import cat.ereza.customactivityoncrash.CustomActivityOnCrash
+import code.name.monkey.retromusic.R
+import code.name.monkey.retromusic.util.FileUtils.createFile
+import code.name.monkey.retromusic.util.Share.shareFile
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import java.text.DateFormat
+import java.text.SimpleDateFormat
+import java.util.*
+
+class ErrorActivity : AppCompatActivity() {
+ private val dayFormat: DateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
+ private val reportPrefix = "bug_report-"
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(cat.ereza.customactivityoncrash.R.layout.customactivityoncrash_default_error_activity)
+
+ val restartButton =
+ findViewById(cat.ereza.customactivityoncrash.R.id.customactivityoncrash_error_activity_restart_button)
+
+ val config = CustomActivityOnCrash.getConfigFromIntent(intent)
+ if (config == null) {
+ finish()
+ return
+ }
+ restartButton.setText(cat.ereza.customactivityoncrash.R.string.customactivityoncrash_error_activity_restart_app)
+ restartButton.setOnClickListener {
+ CustomActivityOnCrash.restartApplication(
+ this@ErrorActivity,
+ config
+ )
+ }
+ val moreInfoButton =
+ findViewById(cat.ereza.customactivityoncrash.R.id.customactivityoncrash_error_activity_more_info_button)
+
+ moreInfoButton.setOnClickListener { //We retrieve all the error data and show it
+ MaterialAlertDialogBuilder(this@ErrorActivity)
+ .setTitle(cat.ereza.customactivityoncrash.R.string.customactivityoncrash_error_activity_error_details_title)
+ .setMessage(
+ CustomActivityOnCrash.getAllErrorDetailsFromIntent(
+ this@ErrorActivity,
+ intent
+ )
+ )
+ .setPositiveButton(
+ cat.ereza.customactivityoncrash.R.string.customactivityoncrash_error_activity_error_details_close,
+ null
+ )
+ .setNeutralButton(
+ R.string.customactivityoncrash_error_activity_error_details_share
+ ) { _, _ ->
+
+ val bugReport = createFile(
+ context = this,
+ "Bug Report",
+ "$reportPrefix${dayFormat.format(Date())}",
+ CustomActivityOnCrash.getAllErrorDetailsFromIntent(
+ this@ErrorActivity,
+ intent
+ ), ".txt"
+ )
+ shareFile(this, bugReport, "text/*")
+ }
+ .show()
+ }
+ val errorActivityDrawableId = config.errorDrawable
+ val errorImageView =
+ findViewById(cat.ereza.customactivityoncrash.R.id.customactivityoncrash_error_activity_image)
+ if (errorActivityDrawableId != null) {
+ errorImageView.setImageResource(
+ errorActivityDrawableId
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/GenreDetailsActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/GenreDetailsActivity.kt
deleted file mode 100644
index 809fbaaec..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/activities/GenreDetailsActivity.kt
+++ /dev/null
@@ -1,162 +0,0 @@
-package code.name.monkey.retromusic.activities
-
-import android.os.Bundle
-import android.view.Menu
-import android.view.MenuItem
-import android.view.View
-import androidx.recyclerview.widget.DefaultItemAnimator
-import androidx.recyclerview.widget.LinearLayoutManager
-import androidx.recyclerview.widget.RecyclerView
-import code.name.monkey.appthemehelper.util.ATHUtil
-import code.name.monkey.retromusic.App
-import code.name.monkey.retromusic.R
-import code.name.monkey.retromusic.activities.base.AbsSlidingMusicPanelActivity
-import code.name.monkey.retromusic.adapter.song.ShuffleButtonSongAdapter
-import code.name.monkey.retromusic.extensions.applyToolbar
-import code.name.monkey.retromusic.helper.menu.GenreMenuHelper
-import code.name.monkey.retromusic.interfaces.CabHolder
-import code.name.monkey.retromusic.model.Genre
-import code.name.monkey.retromusic.model.Song
-import code.name.monkey.retromusic.mvp.presenter.GenreDetailsPresenter
-import code.name.monkey.retromusic.mvp.presenter.GenreDetailsView
-import code.name.monkey.retromusic.util.DensityUtil
-import code.name.monkey.retromusic.util.RetroColorUtil
-import com.afollestad.materialcab.MaterialCab
-import kotlinx.android.synthetic.main.activity_playlist_detail.*
-import java.util.*
-import javax.inject.Inject
-
-/**
- * @author Hemanth S (h4h13).
- */
-
-class GenreDetailsActivity : AbsSlidingMusicPanelActivity(), CabHolder, GenreDetailsView {
-
- @Inject
- lateinit var genreDetailsPresenter: GenreDetailsPresenter
-
- private lateinit var genre: Genre
- private lateinit var songAdapter: ShuffleButtonSongAdapter
- private var cab: MaterialCab? = null
-
- private fun getEmojiByUnicode(unicode: Int): String {
- return String(Character.toChars(unicode))
- }
-
- private fun checkIsEmpty() {
- checkForPadding()
- emptyEmoji.text = getEmojiByUnicode(0x1F631)
- empty?.visibility = if (songAdapter.itemCount == 0) View.VISIBLE else View.GONE
- }
-
- private fun checkForPadding() {
- val height = DensityUtil.dip2px(this, 52f)
- recyclerView.setPadding(0, 0, 0, (height))
- }
-
- override fun onCreate(savedInstanceState: Bundle?) {
- setDrawUnderStatusBar()
- super.onCreate(savedInstanceState)
- setStatusbarColorAuto()
- setNavigationbarColorAuto()
- setTaskDescriptionColorAuto()
- setLightNavigationBar(true)
- setBottomBarVisibility(View.GONE)
- if (intent.extras != null) {
- genre = intent?.extras?.getParcelable(EXTRA_GENRE_ID)!!
- } else {
- finish()
- }
-
- setUpToolBar()
- setupRecyclerView()
-
- App.musicComponent.inject(this)
- genreDetailsPresenter.attachView(this)
- }
-
- private fun setUpToolBar() {
- applyToolbar(toolbar)
- title = genre.name
- }
-
- override fun onResume() {
- super.onResume()
- genreDetailsPresenter.loadGenreSongs(genre.id)
- }
-
- override fun onDestroy() {
- super.onDestroy()
- genreDetailsPresenter.detachView()
- }
-
- override fun createContentView(): View {
- return wrapSlidingMusicPanel(R.layout.activity_playlist_detail)
- }
-
- override fun showEmptyView() {
- }
-
- override fun onCreateOptionsMenu(menu: Menu): Boolean {
- menuInflater.inflate(R.menu.menu_genre_detail, menu)
- return super.onCreateOptionsMenu(menu)
- }
-
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- if (item.itemId == android.R.id.home) {
- onBackPressed()
- }
- return GenreMenuHelper.handleMenuClick(this, genre, item)
- }
-
- private fun setupRecyclerView() {
- songAdapter = ShuffleButtonSongAdapter(this, ArrayList(), R.layout.item_list, this)
- recyclerView.apply {
- itemAnimator = DefaultItemAnimator()
- layoutManager = LinearLayoutManager(this@GenreDetailsActivity)
- adapter = songAdapter
- }
- songAdapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
- override fun onChanged() {
- super.onChanged()
- checkIsEmpty()
- }
- })
- }
-
- override fun songs(songs: List) {
- songAdapter.swapDataSet(songs)
- }
-
- override fun openCab(menuRes: Int, callback: MaterialCab.Callback): MaterialCab {
- if (cab != null && cab!!.isActive) cab?.finish()
- cab = MaterialCab(this, R.id.cab_stub).setMenu(menuRes)
- .setCloseDrawableRes(R.drawable.ic_close_white_24dp)
- .setBackgroundColor(
- RetroColorUtil.shiftBackgroundColorForLightText(
- ATHUtil.resolveColor(
- this,
- R.attr.colorSurface
- )
- )
- ).start(callback)
- return cab!!
- }
-
- override fun onBackPressed() {
- if (cab != null && cab!!.isActive) cab!!.finish()
- else {
- recyclerView!!.stopScroll()
- super.onBackPressed()
- }
- }
-
- override fun onMediaStoreChanged() {
- super.onMediaStoreChanged()
- genreDetailsPresenter.loadGenreSongs(genre.id)
- }
-
- companion object {
- const val EXTRA_GENRE_ID = "extra_genre_id"
- }
-}
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/LicenseActivity.java b/app/src/main/java/code/name/monkey/retromusic/activities/LicenseActivity.java
deleted file mode 100644
index eea9299cc..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/activities/LicenseActivity.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2019 Hemanth Savarala.
- *
- * Licensed under the GNU General Public License v3
- *
- * This is free software: you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by
- * the Free Software Foundation either version 3 of the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- */
-
-package code.name.monkey.retromusic.activities;
-
-import android.graphics.Color;
-import android.os.Bundle;
-import android.view.MenuItem;
-import android.webkit.WebView;
-
-import androidx.annotation.NonNull;
-import androidx.appcompat.widget.Toolbar;
-
-import org.jetbrains.annotations.Nullable;
-
-import java.io.BufferedReader;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.nio.charset.StandardCharsets;
-
-import code.name.monkey.appthemehelper.ThemeStore;
-import code.name.monkey.appthemehelper.util.ATHUtil;
-import code.name.monkey.appthemehelper.util.ColorUtil;
-import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
-import code.name.monkey.retromusic.R;
-import code.name.monkey.retromusic.activities.base.AbsBaseActivity;
-
-/**
- * Created by hemanths on 2019-09-27.
- */
-public class LicenseActivity extends AbsBaseActivity {
-
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- setDrawUnderStatusBar();
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_license);
- setStatusbarColorAuto();
- setNavigationbarColorAuto();
- setLightNavigationBar(true);
- Toolbar toolbar = findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
- ToolbarContentTintHelper.colorBackButton(toolbar);
- toolbar.setBackgroundColor(ATHUtil.INSTANCE.resolveColor(this, R.attr.colorSurface));
- WebView webView = findViewById(R.id.license);
- try {
- StringBuilder buf = new StringBuilder();
- InputStream json = getAssets().open("oldindex.html");
- BufferedReader in = new BufferedReader(new InputStreamReader(json, StandardCharsets.UTF_8));
- String str;
- while ((str = in.readLine()) != null) {
- buf.append(str);
- }
- in.close();
-
- // Inject color values for WebView body background and links
- final boolean isDark = ATHUtil.INSTANCE.isWindowBackgroundDark(this);
- final String backgroundColor = colorToCSS(ATHUtil.INSTANCE.resolveColor(this, R.attr.colorSurface,
- Color.parseColor(isDark ? "#424242" : "#ffffff")));
- final String contentColor = colorToCSS(Color.parseColor(isDark ? "#ffffff" : "#000000"));
- final String changeLog = buf.toString()
- .replace("{style-placeholder}",
- String.format("body { background-color: %s; color: %s; }", backgroundColor, contentColor))
- .replace("{link-color}", colorToCSS(ThemeStore.Companion.accentColor(this)))
- .replace("{link-color-active}",
- colorToCSS(ColorUtil.INSTANCE.lightenColor(ThemeStore.Companion.accentColor(this))));
-
- webView.loadData(changeLog, "text/html", "UTF-8");
- } catch (Throwable e) {
- webView.loadData("Unable to load " + e.getLocalizedMessage() + "
", "text/html", "UTF-8");
- }
-
- }
-
- @Override
- public boolean onOptionsItemSelected(@NonNull MenuItem item) {
- if (item.getItemId() == android.R.id.home) {
- onBackPressed();
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
-
- private String colorToCSS(int color) {
- return String.format("rgb(%d, %d, %d)", Color.red(color), Color.green(color),
- Color.blue(color)); // on API 29, WebView doesn't load with hex colors
- }
-}
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/LicenseActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/LicenseActivity.kt
new file mode 100644
index 000000000..e41352dae
--- /dev/null
+++ b/app/src/main/java/code/name/monkey/retromusic/activities/LicenseActivity.kt
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2019 Hemanth Savarala.
+ *
+ * Licensed under the GNU General Public License v3
+ *
+ * This is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by
+ * the Free Software Foundation either version 3 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ */
+package code.name.monkey.retromusic.activities
+
+import android.graphics.Color
+import android.os.Bundle
+import android.view.MenuItem
+import code.name.monkey.appthemehelper.util.ATHUtil.isWindowBackgroundDark
+import code.name.monkey.appthemehelper.util.ColorUtil.lightenColor
+import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
+import code.name.monkey.retromusic.activities.base.AbsThemeActivity
+import code.name.monkey.retromusic.databinding.ActivityLicenseBinding
+import code.name.monkey.retromusic.extensions.accentColor
+import code.name.monkey.retromusic.extensions.drawAboveSystemBars
+import code.name.monkey.retromusic.extensions.surfaceColor
+import java.io.BufferedReader
+import java.io.InputStreamReader
+import java.nio.charset.StandardCharsets
+
+/** Created by hemanths on 2019-09-27. */
+class LicenseActivity : AbsThemeActivity() {
+ private lateinit var binding: ActivityLicenseBinding
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = ActivityLicenseBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+ setSupportActionBar(binding.toolbar)
+ ToolbarContentTintHelper.colorBackButton(binding.toolbar)
+ try {
+ val buf = StringBuilder()
+ val json = assets.open("license.html")
+ BufferedReader(InputStreamReader(json, StandardCharsets.UTF_8)).use { br ->
+ var str: String?
+ while (br.readLine().also { str = it } != null) {
+ buf.append(str)
+ }
+ }
+
+ // Inject color values for WebView body background and links
+ val isDark = isWindowBackgroundDark(this)
+ val backgroundColor = colorToCSS(
+ surfaceColor(Color.parseColor(if (isDark) "#424242" else "#ffffff"))
+ )
+ val contentColor = colorToCSS(Color.parseColor(if (isDark) "#ffffff" else "#000000"))
+ val changeLog = buf.toString()
+ .replace(
+ "{style-placeholder}", String.format(
+ "body { background-color: %s; color: %s; }", backgroundColor, contentColor
+ )
+ )
+ .replace("{link-color}", colorToCSS(accentColor()))
+ .replace(
+ "{link-color-active}",
+ colorToCSS(
+ lightenColor(accentColor())
+ )
+ )
+ binding.license.loadData(changeLog, "text/html", "UTF-8")
+ } catch (e: Throwable) {
+ binding.license.loadData(
+ "Unable to load " + e.localizedMessage + "
", "text/html", "UTF-8"
+ )
+ }
+ binding.license.drawAboveSystemBars()
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ if (item.itemId == android.R.id.home) {
+ onBackPressedDispatcher.onBackPressed()
+ return true
+ }
+ return super.onOptionsItemSelected(item)
+ }
+
+ private fun colorToCSS(color: Int): String {
+ return String.format(
+ "rgb(%d, %d, %d)",
+ Color.red(color),
+ Color.green(color),
+ Color.blue(color)
+ ) // on API 29, WebView doesn't load with hex colors
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/LockScreenActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/LockScreenActivity.kt
index 8520f8c12..3ac219871 100644
--- a/app/src/main/java/code/name/monkey/retromusic/activities/LockScreenActivity.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/activities/LockScreenActivity.kt
@@ -1,17 +1,35 @@
+/*
+ * Copyright (c) 2020 Hemanth Savarla.
+ *
+ * Licensed under the GNU General Public License v3
+ *
+ * This is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ */
package code.name.monkey.retromusic.activities
import android.app.KeyguardManager
-import android.content.Context
-import android.os.Build
import android.os.Bundle
-import android.view.View
import android.view.WindowManager
-import androidx.core.view.ViewCompat
+import androidx.core.content.getSystemService
+import code.name.monkey.appthemehelper.util.VersionUtils
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.activities.base.AbsMusicServiceActivity
-import code.name.monkey.retromusic.fragments.player.lockscreen.LockScreenPlayerControlsFragment
+import code.name.monkey.retromusic.databinding.ActivityLockScreenBinding
+import code.name.monkey.retromusic.extensions.hideStatusBar
+import code.name.monkey.retromusic.extensions.setTaskDescriptionColorAuto
+import code.name.monkey.retromusic.extensions.whichFragment
+import code.name.monkey.retromusic.fragments.player.lockscreen.LockScreenControlsFragment
+import code.name.monkey.retromusic.glide.RetroGlideExtension
+import code.name.monkey.retromusic.glide.RetroGlideExtension.asBitmapPalette
+import code.name.monkey.retromusic.glide.RetroGlideExtension.songCoverOptions
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
-import code.name.monkey.retromusic.glide.SongGlideRequest
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.bumptech.glide.Glide
@@ -19,30 +37,18 @@ import com.r0adkll.slidr.Slidr
import com.r0adkll.slidr.model.SlidrConfig
import com.r0adkll.slidr.model.SlidrListener
import com.r0adkll.slidr.model.SlidrPosition
-import kotlinx.android.synthetic.main.activity_lock_screen.*
class LockScreenActivity : AbsMusicServiceActivity() {
- private var fragment: LockScreenPlayerControlsFragment? = null
+ private lateinit var binding: ActivityLockScreenBinding
+ private var fragment: LockScreenControlsFragment? = null
override fun onCreate(savedInstanceState: Bundle?) {
- setDrawUnderStatusBar()
super.onCreate(savedInstanceState)
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
- setShowWhenLocked(true)
- setTurnScreenOn(true)
- } else {
- this.window.addFlags(
- WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or
- WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
- WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
- )
- }
- setContentView(R.layout.activity_lock_screen)
+ lockScreenInit()
+ binding = ActivityLockScreenBinding.inflate(layoutInflater)
+ setContentView(binding.root)
hideStatusBar()
- setStatusbarColorAuto()
- setNavigationbarColorAuto()
setTaskDescriptionColorAuto()
- setLightNavigationBar(true)
val config = SlidrConfig.Builder().listener(object : SlidrListener {
override fun onSlideStateChanged(state: Int) {
@@ -55,10 +61,10 @@ class LockScreenActivity : AbsMusicServiceActivity() {
}
override fun onSlideClosed(): Boolean {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ if (VersionUtils.hasOreo()) {
val keyguardManager =
- getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
- keyguardManager.requestDismissKeyguard(this@LockScreenActivity, null)
+ getSystemService()
+ keyguardManager?.requestDismissKeyguard(this@LockScreenActivity, null)
}
finish()
return true
@@ -67,13 +73,25 @@ class LockScreenActivity : AbsMusicServiceActivity() {
Slidr.attach(this, config)
- fragment =
- supportFragmentManager.findFragmentById(R.id.playback_controls_fragment) as LockScreenPlayerControlsFragment?
+ fragment = whichFragment(R.id.playback_controls_fragment)
- findViewById(R.id.slide).apply {
+ binding.slide.apply {
translationY = 100f
alpha = 0f
- ViewCompat.animate(this).translationY(0f).alpha(1f).setDuration(1500).start()
+ animate().translationY(0f).alpha(1f).setDuration(1500).start()
+ }
+ }
+
+ @Suppress("Deprecation")
+ private fun lockScreenInit() {
+ if (VersionUtils.hasOreoMR1()) {
+ setShowWhenLocked(true)
+ //setTurnScreenOn(true)
+ } else {
+ window.addFlags(
+ WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
+ // or WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
+ )
}
}
@@ -89,12 +107,15 @@ class LockScreenActivity : AbsMusicServiceActivity() {
private fun updateSongs() {
val song = MusicPlayerRemote.currentSong
- SongGlideRequest.Builder.from(Glide.with(this), song).checkIgnoreMediaStore(this)
- .generatePalette(this).build().dontAnimate()
- .into(object : RetroMusicColoredTarget(image) {
+ Glide.with(this)
+ .asBitmapPalette()
+ .songCoverOptions(song)
+ .load(RetroGlideExtension.getSongModel(song))
+ .dontAnimate()
+ .into(object : RetroMusicColoredTarget(binding.image) {
override fun onColorReady(colors: MediaNotificationProcessor) {
fragment?.setColor(colors)
}
})
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/LyricsActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/LyricsActivity.kt
deleted file mode 100644
index c0a7efff5..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/activities/LyricsActivity.kt
+++ /dev/null
@@ -1,420 +0,0 @@
-package code.name.monkey.retromusic.activities
-
-import android.R.attr
-import android.annotation.SuppressLint
-import android.content.res.ColorStateList
-import android.os.AsyncTask
-import android.os.Build
-import android.os.Bundle
-import android.text.TextUtils
-import android.view.*
-import androidx.annotation.StringRes
-import androidx.core.content.ContextCompat
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.FragmentManager
-import androidx.fragment.app.FragmentStatePagerAdapter
-import androidx.viewpager.widget.ViewPager
-import code.name.monkey.appthemehelper.ThemeStore
-import code.name.monkey.appthemehelper.util.ATHUtil.resolveColor
-import code.name.monkey.appthemehelper.util.ColorUtil
-import code.name.monkey.appthemehelper.util.MaterialValueHelper
-import code.name.monkey.appthemehelper.util.TintHelper
-import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
-import code.name.monkey.retromusic.App
-import code.name.monkey.retromusic.R
-import code.name.monkey.retromusic.activities.base.AbsMusicServiceActivity
-import code.name.monkey.retromusic.extensions.surfaceColor
-import code.name.monkey.retromusic.extensions.textColorSecondary
-import code.name.monkey.retromusic.fragments.base.AbsMusicServiceFragment
-import code.name.monkey.retromusic.helper.MusicPlayerRemote
-import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
-import code.name.monkey.retromusic.lyrics.LrcHelper
-import code.name.monkey.retromusic.lyrics.LrcView
-import code.name.monkey.retromusic.model.Song
-import code.name.monkey.retromusic.model.lyrics.Lyrics
-import code.name.monkey.retromusic.util.LyricUtil
-import code.name.monkey.retromusic.util.MusicUtil
-import code.name.monkey.retromusic.util.PreferenceUtil
-import kotlinx.android.synthetic.main.activity_lyrics.*
-import kotlinx.android.synthetic.main.fragment_lyrics.*
-import kotlinx.android.synthetic.main.fragment_synced.*
-import java.io.File
-
-class LyricsActivity : AbsMusicServiceActivity(), View.OnClickListener,
- ViewPager.OnPageChangeListener {
- override fun onPageScrollStateChanged(state: Int) {
- when (state) {
- ViewPager.SCROLL_STATE_IDLE -> fab.show()
- ViewPager.SCROLL_STATE_DRAGGING,
- ViewPager.SCROLL_STATE_SETTLING -> fab.hide()
- }
- }
-
- override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
- }
-
- override fun onPageSelected(position: Int) {
- PreferenceUtil.lyricsOption = position
- if (position == 0) fab.text = getString(R.string.synced_lyrics)
- else if (position == 1) fab.text = getString(R.string.lyrics)
- }
-
- override fun onClick(v: View?) {
- when (viewPager.currentItem) {
- 0 -> showSyncedLyrics()
- 1 -> showLyricsSaveDialog()
- }
- }
-
- private lateinit var song: Song
- private var lyricsString: String? = null
-
- private val googleSearchLrcUrl: String
- get() {
- var baseUrl = "http://www.google.com/search?"
- var query = song.title + "+" + song.artistName
- query = "q=" + query.replace(" ", "+") + " .lrc"
- baseUrl += query
- return baseUrl
- }
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_lyrics)
- setStatusbarColorAuto()
- setTaskDescriptionColorAuto()
- setNavigationbarColorAuto()
-
- fab.backgroundTintList = ColorStateList.valueOf(ThemeStore.accentColor(this))
- ColorStateList.valueOf(
- MaterialValueHelper.getPrimaryTextColor(
- this,
- ColorUtil.isColorLight(ThemeStore.accentColor(this))
- )
- )
- .apply {
- fab.setTextColor(this)
- fab.iconTint = this
- }
- setupWakelock()
-
- viewPager.apply {
- adapter = PagerAdapter(supportFragmentManager)
- currentItem = PreferenceUtil.lyricsOption
- addOnPageChangeListener(this@LyricsActivity)
- }
-
-
- toolbar.setBackgroundColor(surfaceColor())
- tabs.setBackgroundColor(surfaceColor())
- ToolbarContentTintHelper.colorBackButton(toolbar)
- setSupportActionBar(toolbar)
- tabs.setupWithViewPager(viewPager)
- tabs.setSelectedTabIndicator(
- TintHelper.createTintedDrawable(
- ContextCompat.getDrawable(
- this,
- R.drawable.tab_indicator
- ), ThemeStore.accentColor(this)
- )
- )
- tabs.setTabTextColors(
- textColorSecondary(),
- ThemeStore.accentColor(this)
- )
- tabs.setSelectedTabIndicatorColor(ThemeStore.accentColor(this))
-
- fab.setOnClickListener(this)
- }
-
- override fun onPlayingMetaChanged() {
- super.onPlayingMetaChanged()
- updateTitleSong()
- }
-
- override fun onServiceConnected() {
- super.onServiceConnected()
- updateTitleSong()
- }
-
- private fun updateTitleSong() {
- song = MusicPlayerRemote.currentSong
- toolbar.title = song.title
- toolbar.subtitle = song.artistName
- }
-
- private fun setupWakelock() {
- window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
- }
-
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- if (item.itemId == android.R.id.home) {
- finish()
- return true
- }
- return super.onOptionsItemSelected(item)
- }
-
- private fun showSyncedLyrics() {
- var content = ""
- try {
- content = LyricUtil.getStringFromFile(song.title, song.artistName)
- } catch (e: Exception) {
- e.printStackTrace()
- }
-
- /*val materialDialog = MaterialDialog(this)
- .show {
- title(R.string.add_time_framed_lryics)
- negativeButton(R.string.action_search) {
- RetroUtil.openUrl(this@LyricsActivity, googleSearchLrcUrl)
- }
- input(
- hint = getString(R.string.paste_lyrics_here),
- prefill = content,
- inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_MULTI_LINE
- ) { _, input ->
- LyricUtil.writeLrcToLoc(song.title, song.artistName, input.toString())
- }
- positiveButton(android.R.string.ok) {
- updateSong()
- }
- }
-
- MaterialUtil.setTint(materialDialog.getInputLayout(), false)*/
- }
-
- private fun updateSong() {
- val page =
- supportFragmentManager.findFragmentByTag("android:switcher:" + R.id.viewPager + ":" + viewPager.currentItem)
- if (viewPager.currentItem == 0 && page != null) {
- (page as BaseLyricsFragment).upDateSong()
- }
- }
-
- private fun showLyricsSaveDialog() {
- val content: String = if (lyricsString == null) {
- ""
- } else {
- lyricsString!!
- }
-
- /*val materialDialog = MaterialDialog(
- this
- ).show {
-
- title(R.string.add_lyrics)
- negativeButton(R.string.action_search) {
- RetroUtil.openUrl(this@LyricsActivity, getGoogleSearchUrl())
- }
- input(
- hint = getString(R.string.paste_lyrics_here),
- prefill = content,
- inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_MULTI_LINE
- ) { _, input ->
- val fieldKeyValueMap = EnumMap(FieldKey::class.java)
- fieldKeyValueMap[FieldKey.LYRICS] = input.toString()
- WriteTagsAsyncTask(this@LyricsActivity).execute(
- WriteTagsAsyncTask.LoadingInfo(
- getSongPaths(song), fieldKeyValueMap, null
- )
- )
- }
- positiveButton(android.R.string.ok) {
- updateSong()
- }
- }
- MaterialUtil.setTint(materialDialog.getInputLayout(), false)*/
- }
-
- private fun getSongPaths(song: Song): ArrayList {
- val paths = ArrayList(1)
- paths.add(song.data)
- return paths
- }
-
- private fun getGoogleSearchUrl(): String {
- var baseUrl = "http://www.google.com/search?"
- var query = song.title + "+" + song.artistName
- query = "q=" + query.replace(" ", "+") + " lyrics"
- baseUrl += query
- return baseUrl
- }
-
- class PagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(
- fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT
- ) {
-
- class Tabs(
- @StringRes val title: Int, val fragment: Fragment
- )
-
- private var tabs = ArrayList()
-
- init {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
- tabs.add(Tabs(R.string.synced_lyrics, SyncedLyricsFragment()))
- }
- tabs.add(Tabs(R.string.normal_lyrics, OfflineLyricsFragment()))
- }
-
- override fun getItem(position: Int): Fragment {
- return tabs[position].fragment
- }
-
- override fun getPageTitle(position: Int): CharSequence? {
- return App.getContext().getString(tabs[position].title)
- }
-
- override fun getCount(): Int {
- return tabs.size
- }
- }
-
- abstract class BaseLyricsFragment : AbsMusicServiceFragment() {
- abstract fun upDateSong()
-
- override fun onPlayingMetaChanged() {
- super.onPlayingMetaChanged()
- upDateSong()
- }
-
- override fun onServiceConnected() {
- super.onServiceConnected()
- upDateSong()
- }
- }
-
- class OfflineLyricsFragment : BaseLyricsFragment() {
- override fun upDateSong() {
- loadSongLyrics()
- }
-
- private var updateLyricsAsyncTask: AsyncTask<*, *, *>? = null
- private var lyrics: Lyrics? = null
-
- @SuppressLint("StaticFieldLeak")
- private fun loadSongLyrics() {
- if (updateLyricsAsyncTask != null) {
- updateLyricsAsyncTask!!.cancel(false)
- }
- val song = MusicPlayerRemote.currentSong
- updateLyricsAsyncTask = object : AsyncTask() {
- override fun doInBackground(vararg params: Void?): Lyrics? {
- val data = MusicUtil.getLyrics(song)
- return if (TextUtils.isEmpty(data)) {
- null
- } else Lyrics.parse(song, data!!)
- }
-
- override fun onPreExecute() {
- super.onPreExecute()
- lyrics = null
- }
-
- override fun onPostExecute(l: Lyrics?) {
- lyrics = l
- offlineLyrics?.visibility = View.VISIBLE
- if (l == null) {
- offlineLyrics?.setText(R.string.no_lyrics_found)
- return
- }
- (activity as LyricsActivity).lyricsString = l.text
- offlineLyrics?.text = l.text
- }
-
- override fun onCancelled(s: Lyrics?) {
- onPostExecute(null)
- }
- }.execute()
- }
-
- override fun onActivityCreated(savedInstanceState: Bundle?) {
- super.onActivityCreated(savedInstanceState)
- loadSongLyrics()
- }
-
- override fun onDestroyView() {
- super.onDestroyView()
- if (updateLyricsAsyncTask != null && !updateLyricsAsyncTask!!.isCancelled) {
- updateLyricsAsyncTask?.cancel(true)
- }
- }
-
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
- ): View? {
- return inflater.inflate(R.layout.fragment_lyrics, container, false)
- }
- }
-
- class SyncedLyricsFragment : BaseLyricsFragment(), MusicProgressViewUpdateHelper.Callback {
- override fun upDateSong() {
- loadLRCLyrics()
- }
-
- private lateinit var updateHelper: MusicProgressViewUpdateHelper
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
- ): View? {
- return inflater.inflate(R.layout.fragment_synced, container, false)
- }
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- updateHelper = MusicProgressViewUpdateHelper(this, 500, 1000)
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
- setupLyricsView()
- }
-
- private fun setupLyricsView() {
- lyricsView.apply {
- setCurrentPlayLineColor(ThemeStore.accentColor(requireContext()))
- setIndicatorTextColor(ThemeStore.accentColor(requireContext()))
- setCurrentIndicateLineTextColor(
- resolveColor(
- requireContext(),
- attr.textColorPrimary
- )
- )
- setNoLrcTextColor(resolveColor(requireContext(), attr.textColorPrimary))
- setOnPlayIndicatorLineListener(object : LrcView.OnPlayIndicatorLineListener {
- override fun onPlay(time: Long, content: String) {
- MusicPlayerRemote.seekTo(time.toInt())
- }
- })
- }
- }
-
- override fun onResume() {
- super.onResume()
- updateHelper.start()
- }
-
- override fun onPause() {
- super.onPause()
- updateHelper.stop()
- }
-
- override fun onUpdateProgressViews(progress: Int, total: Int) {
- lyricsView.updateTime(progress.toLong())
- }
-
- private fun loadLRCLyrics() {
- lyricsView.resetView("Empty")
- val song = MusicPlayerRemote.currentSong
- if (LyricUtil.isLrcFileExist(song.title, song.artistName)) {
- showLyricsLocal(LyricUtil.getLocalLyricFile(song.title, song.artistName))
- }
- }
-
- private fun showLyricsLocal(file: File?) {
- if (file != null) {
- lyricsView.setLrcData(LrcHelper.parseLrcFromFile(file))
- }
- }
- }
-}
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/MainActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/MainActivity.kt
index f9560e3c3..e9cb29abe 100644
--- a/app/src/main/java/code/name/monkey/retromusic/activities/MainActivity.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/activities/MainActivity.kt
@@ -1,747 +1,202 @@
+/*
+ * Copyright (c) 2020 Hemanth Savarla.
+ *
+ * Licensed under the GNU General Public License v3
+ *
+ * This is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ */
package code.name.monkey.retromusic.activities
-import android.app.ActivityOptions
-import android.content.*
-import android.content.IntentSender.SendIntentException
+import android.content.Intent
+import android.net.Uri
import android.os.Bundle
import android.provider.MediaStore
-import android.util.Log
-import android.view.Menu
-import android.view.MenuItem
-import android.view.SubMenu
-import android.view.View
-import androidx.core.app.ActivityCompat
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.commit
-import androidx.lifecycle.ViewModelProvider
-import code.name.monkey.appthemehelper.ThemeStore.Companion.accentColor
-import code.name.monkey.appthemehelper.util.ATHUtil
-import code.name.monkey.appthemehelper.util.ATHUtil.resolveColor
-import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
-import code.name.monkey.retromusic.*
+import androidx.lifecycle.lifecycleScope
+import androidx.navigation.contains
+import androidx.navigation.ui.setupWithNavController
+import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.activities.base.AbsSlidingMusicPanelActivity
-import code.name.monkey.retromusic.dialogs.CreatePlaylistDialog.Companion.create
-import code.name.monkey.retromusic.fragments.LibraryViewModel
-import code.name.monkey.retromusic.fragments.albums.AlbumsFragment
-import code.name.monkey.retromusic.fragments.artists.ArtistsFragment
-import code.name.monkey.retromusic.fragments.base.AbsLibraryPagerRecyclerViewCustomGridSizeFragment
-import code.name.monkey.retromusic.fragments.genres.GenresFragment
-import code.name.monkey.retromusic.fragments.home.BannerHomeFragment
-import code.name.monkey.retromusic.fragments.mainactivity.FoldersFragment
-import code.name.monkey.retromusic.fragments.playlists.PlaylistsFragment
-import code.name.monkey.retromusic.fragments.queue.PlayingQueueFragment
-import code.name.monkey.retromusic.fragments.songs.SongsFragment
-import code.name.monkey.retromusic.helper.MusicPlayerRemote.isPlaying
-import code.name.monkey.retromusic.helper.MusicPlayerRemote.openAndShuffleQueue
-import code.name.monkey.retromusic.helper.MusicPlayerRemote.openQueue
-import code.name.monkey.retromusic.helper.MusicPlayerRemote.playFromUri
-import code.name.monkey.retromusic.helper.MusicPlayerRemote.shuffleMode
+import code.name.monkey.retromusic.extensions.*
+import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.SearchQueryHelper.getSongs
-import code.name.monkey.retromusic.helper.SortOrder.*
-import code.name.monkey.retromusic.interfaces.CabHolder
-import code.name.monkey.retromusic.interfaces.MainActivityFragmentCallbacks
-import code.name.monkey.retromusic.loaders.AlbumLoader.getAlbum
-import code.name.monkey.retromusic.loaders.ArtistLoader.getArtist
-import code.name.monkey.retromusic.loaders.PlaylistSongsLoader.getPlaylistSongList
+import code.name.monkey.retromusic.interfaces.IScrollHelper
+import code.name.monkey.retromusic.model.CategoryInfo
import code.name.monkey.retromusic.model.Song
+import code.name.monkey.retromusic.repository.PlaylistSongsLoader
import code.name.monkey.retromusic.service.MusicService
-import code.name.monkey.retromusic.util.AppRater.appLaunched
-import code.name.monkey.retromusic.util.NavigationUtil
import code.name.monkey.retromusic.util.PreferenceUtil
-import code.name.monkey.retromusic.util.RetroColorUtil
-import code.name.monkey.retromusic.util.RetroUtil
-import com.afollestad.materialcab.MaterialCab
-import com.google.android.material.appbar.AppBarLayout
-import com.google.android.material.snackbar.Snackbar
-import com.google.android.play.core.appupdate.AppUpdateInfo
-import com.google.android.play.core.appupdate.AppUpdateManager
-import com.google.android.play.core.appupdate.AppUpdateManagerFactory
-import com.google.android.play.core.install.InstallState
-import com.google.android.play.core.install.InstallStateUpdatedListener
-import com.google.android.play.core.install.model.AppUpdateType
-import com.google.android.play.core.install.model.InstallStatus.DOWNLOADED
-import com.google.android.play.core.install.model.InstallStatus.INSTALLED
-import com.google.android.play.core.install.model.UpdateAvailability
-import com.google.android.play.core.tasks.Task
-import kotlinx.android.synthetic.main.activity_main_content.*
-import java.util.*
+import code.name.monkey.retromusic.util.logE
+import kotlinx.coroutines.Dispatchers.IO
+import kotlinx.coroutines.launch
+import org.koin.android.ext.android.get
-class MainActivity : AbsSlidingMusicPanelActivity(),
- SharedPreferences.OnSharedPreferenceChangeListener, CabHolder {
+class MainActivity : AbsSlidingMusicPanelActivity() {
companion object {
const val TAG = "MainActivity"
const val EXPAND_PANEL = "expand_panel"
- const val APP_UPDATE_REQUEST_CODE = 9002
- }
-
- lateinit var libraryViewModel: LibraryViewModel
- private var cab: MaterialCab? = null
- private val intentFilter = IntentFilter(Intent.ACTION_SCREEN_OFF)
- private lateinit var currentFragment: MainActivityFragmentCallbacks
- private var appUpdateManager: AppUpdateManager? = null
- private var blockRequestPermissions = false
- private val listener = object : InstallStateUpdatedListener {
- override fun onStateUpdate(state: InstallState) {
- when {
- state.installStatus() == DOWNLOADED -> {
- popupSnackBarForCompleteUpdate()
- }
- state.installStatus() == INSTALLED -> {
- appUpdateManager?.unregisterListener(this)
- }
- else -> {
- Log.i(TAG, "InstallStateUpdatedListener: state: " + state.installStatus())
- }
- }
- }
- }
- private val broadcastReceiver: BroadcastReceiver = object : BroadcastReceiver() {
- override fun onReceive(context: Context, intent: Intent) {
- val action = intent.action
- if (action != null && action == Intent.ACTION_SCREEN_OFF) {
- if (PreferenceUtil.isLockScreen && isPlaying) {
- val activity = Intent(context, LockScreenActivity::class.java)
- activity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- activity.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)
- ActivityCompat.startActivity(context, activity, null)
- }
- }
- }
- }
-
- override fun createContentView(): View {
- return wrapSlidingMusicPanel(R.layout.activity_main_content)
}
override fun onCreate(savedInstanceState: Bundle?) {
- setDrawUnderStatusBar()
super.onCreate(savedInstanceState)
- setStatusbarColorAuto()
- setNavigationbarColorAuto()
- setLightNavigationBar(true)
setTaskDescriptionColorAuto()
hideStatusBar()
- setBottomBarVisibility(View.VISIBLE)
-
- libraryViewModel = ViewModelProvider(this).get(LibraryViewModel::class.java)
- addMusicServiceEventListener(libraryViewModel)
-
- if (savedInstanceState == null) {
- selectedFragment(PreferenceUtil.lastPage)
- } else {
- restoreCurrentFragment()
- }
-
- appLaunched(this)
- setupToolbar()
- checkUpdate()
updateTabs()
- getBottomNavigationView().selectedItemId = PreferenceUtil.lastPage
- getBottomNavigationView().setOnNavigationItemSelectedListener {
- PreferenceUtil.lastPage = it.itemId
- selectedFragment(it.itemId)
- true
- }
+
+ setupNavigationController()
+
+ WhatsNewFragment.showChangeLog(this)
}
- override fun onResume() {
- super.onResume()
- registerReceiver(broadcastReceiver, intentFilter)
- PreferenceUtil.registerOnSharedPreferenceChangedListener(this)
- if (intent.hasExtra(EXPAND_PANEL) &&
- intent.getBooleanExtra(EXPAND_PANEL, false) &&
- PreferenceUtil.isExpandPanel
- ) {
- expandPanel()
- intent.removeExtra(EXPAND_PANEL)
- }
+ private fun setupNavigationController() {
+ val navController = findNavController(R.id.fragment_container)
+ val navInflater = navController.navInflater
+ val navGraph = navInflater.inflate(R.navigation.main_graph)
- appUpdateManager?.appUpdateInfo
- ?.addOnSuccessListener { appUpdateInfo: AppUpdateInfo ->
- if (appUpdateInfo.installStatus() == DOWNLOADED) {
- popupSnackBarForCompleteUpdate()
- }
- try {
- if (appUpdateInfo.updateAvailability() == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS) {
- appUpdateManager!!.startUpdateFlowForResult(
- appUpdateInfo,
- AppUpdateType.IMMEDIATE,
- this,
- APP_UPDATE_REQUEST_CODE
- )
+ val categoryInfo: CategoryInfo = PreferenceUtil.libraryCategory.first { it.visible }
+ if (categoryInfo.visible) {
+ if (!navGraph.contains(PreferenceUtil.lastTab)) PreferenceUtil.lastTab =
+ categoryInfo.category.id
+ navGraph.setStartDestination(
+ if (PreferenceUtil.rememberLastTab) {
+ PreferenceUtil.lastTab.let {
+ if (it == 0) {
+ categoryInfo.category.id
+ } else {
+ it
+ }
}
- } catch (e: SendIntentException) {
- e.printStackTrace()
- }
- }
- }
-
- override fun onDestroy() {
- super.onDestroy()
- unregisterReceiver(broadcastReceiver)
- PreferenceUtil.unregisterOnSharedPreferenceChangedListener(this)
- }
-
- override fun onPrepareOptionsMenu(menu: Menu?): Boolean {
- ToolbarContentTintHelper.handleOnPrepareOptionsMenu(this, toolbar)
- return super.onPrepareOptionsMenu(menu)
- }
-
- override fun onCreateOptionsMenu(menu: Menu?): Boolean {
- menuInflater.inflate(R.menu.menu_main, menu)
- menu ?: return super.onCreateOptionsMenu(menu)
- if (isPlaylistPage()) {
- menu.add(0, R.id.action_new_playlist, 1, R.string.new_playlist_title)
- .setIcon(R.drawable.ic_playlist_add_white_24dp)
- .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM)
+ } else categoryInfo.category.id
+ )
}
- if (isHomePage()) {
- menu.add(0, R.id.action_mic, 1, getString(R.string.action_search))
- .setIcon(R.drawable.ic_mic_white_24dp)
- .setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM)
- }
- if (isFolderPage()) {
- menu.add(0, R.id.action_scan, 0, R.string.scan_media)
- .setIcon(R.drawable.ic_scanner_white_24dp)
- .setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM)
- menu.add(0, R.id.action_go_to_start_directory, 1, R.string.action_go_to_start_directory)
- .setIcon(R.drawable.ic_bookmark_music_white_24dp)
- .setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM)
- }
- val fragment: Fragment? = getCurrentFragment()
- if (fragment != null && fragment is AbsLibraryPagerRecyclerViewCustomGridSizeFragment<*, *>) {
- val gridSizeItem: MenuItem = menu.findItem(R.id.action_grid_size)
- if (RetroUtil.isLandscape()) {
- gridSizeItem.setTitle(R.string.action_grid_size_land)
- }
- setUpGridSizeMenu(fragment, gridSizeItem.subMenu)
- setupLayoutMenu(fragment, menu.findItem(R.id.action_layout_type).subMenu)
- setUpSortOrderMenu(fragment, menu.findItem(R.id.action_sort_order).subMenu)
- } else {
- menu.removeItem(R.id.action_layout_type)
- menu.removeItem(R.id.action_grid_size)
- menu.removeItem(R.id.action_sort_order)
- }
- menu.add(0, R.id.action_settings, 6, getString(R.string.action_settings))
- .setIcon(R.drawable.ic_settings_white_24dp)
- .setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM)
- menu.add(0, R.id.action_search, 0, getString(R.string.action_search))
- .setIcon(R.drawable.ic_search_white_24dp)
- .setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_ALWAYS)
- ToolbarContentTintHelper.handleOnCreateOptionsMenu(
- this,
- toolbar,
- menu,
- getToolbarBackgroundColor(toolbar)
- )
- return super.onCreateOptionsMenu(menu)
- }
-
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- val fragment = getCurrentFragment()
- if (fragment is AbsLibraryPagerRecyclerViewCustomGridSizeFragment<*, *>) {
- if (handleGridSizeMenuItem(fragment, item)) {
- return true
- }
- if (handleLayoutResType(fragment, item)) {
- return true
- }
- if (handleSortOrderMenuItem(fragment, item)) {
- return true
- }
- }
- when (item.itemId) {
- R.id.action_search -> NavigationUtil.goToSearch(this)
- R.id.action_new_playlist -> {
- create().show(supportFragmentManager, "CREATE_PLAYLIST")
- return true
- }
- R.id.action_mic -> {
- val options = ActivityOptions.makeSceneTransitionAnimation(
- this, toolbar,
- getString(R.string.transition_toolbar)
- )
- NavigationUtil.goToSearch(this, true, options)
- return true
- }
- R.id.action_settings -> {
- NavigationUtil.goToSettings(this)
- return true
- }
- }
- return super.onOptionsItemSelected(item)
- }
-
- private fun handleSortOrderMenuItem(
- fragment: AbsLibraryPagerRecyclerViewCustomGridSizeFragment<*, *>,
- item: MenuItem
- ): Boolean {
- var sortOrder: String? = null
- when (fragment) {
- is AlbumsFragment -> {
- when (item.itemId) {
- R.id.action_album_sort_order_asc -> sortOrder = AlbumSortOrder.ALBUM_A_Z
- R.id.action_album_sort_order_desc -> sortOrder = AlbumSortOrder.ALBUM_Z_A
- R.id.action_album_sort_order_artist -> sortOrder = AlbumSortOrder.ALBUM_ARTIST
- R.id.action_album_sort_order_year -> sortOrder = AlbumSortOrder.ALBUM_YEAR
- }
- }
- is ArtistsFragment -> {
- when (item.itemId) {
- R.id.action_artist_sort_order_asc -> sortOrder = ArtistSortOrder.ARTIST_A_Z
- R.id.action_artist_sort_order_desc -> sortOrder = ArtistSortOrder.ARTIST_Z_A
- }
- }
- is SongsFragment -> {
- when (item.itemId) {
- R.id.action_song_sort_order_asc -> sortOrder = SongSortOrder.SONG_A_Z
- R.id.action_song_sort_order_desc -> sortOrder = SongSortOrder.SONG_Z_A
- R.id.action_song_sort_order_artist -> sortOrder = SongSortOrder.SONG_ARTIST
- R.id.action_song_sort_order_album -> sortOrder = SongSortOrder.SONG_ALBUM
- R.id.action_song_sort_order_year -> sortOrder = SongSortOrder.SONG_YEAR
- R.id.action_song_sort_order_date -> sortOrder = SongSortOrder.SONG_DATE
- R.id.action_song_sort_order_composer -> sortOrder = SongSortOrder.COMPOSER
- R.id.action_song_sort_order_date_modified ->
- sortOrder = SongSortOrder.SONG_DATE_MODIFIED
+ navController.graph = navGraph
+ navigationView.setupWithNavController(navController)
+ // Scroll Fragment to top
+ navigationView.setOnItemReselectedListener {
+ currentFragment(R.id.fragment_container).apply {
+ if (this is IScrollHelper) {
+ scrollToTop()
}
}
}
-
- if (sortOrder != null) {
- item.isChecked = true
- fragment.setAndSaveSortOrder(sortOrder)
- return true
- }
-
- return false
- }
-
- private fun handleLayoutResType(
- fragment: AbsLibraryPagerRecyclerViewCustomGridSizeFragment<*, *>,
- item: MenuItem
- ): Boolean {
- var layoutRes = -1
- when (item.itemId) {
- R.id.action_layout_normal -> layoutRes = R.layout.item_grid
- R.id.action_layout_card -> layoutRes = R.layout.item_card
- R.id.action_layout_colored_card -> layoutRes = R.layout.item_card_color
- R.id.action_layout_circular -> layoutRes = R.layout.item_grid_circle
- R.id.action_layout_image -> layoutRes = R.layout.image
- R.id.action_layout_gradient_image -> layoutRes = R.layout.item_image_gradient
- }
- if (layoutRes != -1) {
- item.isChecked = true
- fragment.setAndSaveLayoutRes(layoutRes)
- return true
- }
- return false
- }
-
- private fun handleGridSizeMenuItem(
- fragment: AbsLibraryPagerRecyclerViewCustomGridSizeFragment<*, *>,
- item: MenuItem
- ): Boolean {
- var gridSize = 0
- when (item.itemId) {
- R.id.action_grid_size_1 -> gridSize = 1
- R.id.action_grid_size_2 -> gridSize = 2
- R.id.action_grid_size_3 -> gridSize = 3
- R.id.action_grid_size_4 -> gridSize = 4
- R.id.action_grid_size_5 -> gridSize = 5
- R.id.action_grid_size_6 -> gridSize = 6
- R.id.action_grid_size_7 -> gridSize = 7
- R.id.action_grid_size_8 -> gridSize = 8
- }
- if (gridSize > 0) {
- item.isChecked = true
- fragment.setAndSaveGridSize(gridSize)
- return true
- }
- return false
- }
-
- private fun setUpGridSizeMenu(
- fragment: AbsLibraryPagerRecyclerViewCustomGridSizeFragment<*, *>,
- gridSizeMenu: SubMenu
- ) {
- when (fragment.getGridSize()) {
- 1 -> gridSizeMenu.findItem(R.id.action_grid_size_1).isChecked = true
- 2 -> gridSizeMenu.findItem(R.id.action_grid_size_2).isChecked = true
- 3 -> gridSizeMenu.findItem(R.id.action_grid_size_3).isChecked = true
- 4 -> gridSizeMenu.findItem(R.id.action_grid_size_4).isChecked = true
- 5 -> gridSizeMenu.findItem(R.id.action_grid_size_5).isChecked = true
- 6 -> gridSizeMenu.findItem(R.id.action_grid_size_6).isChecked = true
- 7 -> gridSizeMenu.findItem(R.id.action_grid_size_7).isChecked = true
- 8 -> gridSizeMenu.findItem(R.id.action_grid_size_8).isChecked = true
- }
- val maxGridSize = fragment.maxGridSize
- if (maxGridSize < 8) {
- gridSizeMenu.findItem(R.id.action_grid_size_8).isVisible = false
- }
- if (maxGridSize < 7) {
- gridSizeMenu.findItem(R.id.action_grid_size_7).isVisible = false
- }
- if (maxGridSize < 6) {
- gridSizeMenu.findItem(R.id.action_grid_size_6).isVisible = false
- }
- if (maxGridSize < 5) {
- gridSizeMenu.findItem(R.id.action_grid_size_5).isVisible = false
- }
- if (maxGridSize < 4) {
- gridSizeMenu.findItem(R.id.action_grid_size_4).isVisible = false
- }
- if (maxGridSize < 3) {
- gridSizeMenu.findItem(R.id.action_grid_size_3).isVisible = false
- }
- }
-
- private fun setupLayoutMenu(
- fragment: AbsLibraryPagerRecyclerViewCustomGridSizeFragment<*, *>,
- subMenu: SubMenu
- ) {
- when (fragment.itemLayoutRes()) {
- R.layout.item_card ->
- subMenu.findItem(R.id.action_layout_card).isChecked = true
- R.layout.item_card_color ->
- subMenu.findItem(R.id.action_layout_colored_card).isChecked = true
- R.layout.item_grid_circle ->
- subMenu.findItem(R.id.action_layout_circular).isChecked = true
- R.layout.image ->
- subMenu.findItem(R.id.action_layout_image).isChecked = true
- R.layout.item_image_gradient ->
- subMenu.findItem(R.id.action_layout_gradient_image).isChecked = true
- R.layout.item_grid ->
- subMenu.findItem(R.id.action_layout_normal).isChecked = true
- else ->
- subMenu.findItem(R.id.action_layout_normal).isChecked = true
- }
- }
-
- private fun setUpSortOrderMenu(
- fragment: AbsLibraryPagerRecyclerViewCustomGridSizeFragment<*, *>,
- sortOrderMenu: SubMenu
- ) {
- val currentSortOrder = fragment.getSortOrder()
- sortOrderMenu.clear()
- when (fragment) {
- is AlbumsFragment -> {
- sortOrderMenu.add(
- 0,
- R.id.action_album_sort_order_asc,
- 0,
- R.string.sort_order_a_z
- ).isChecked = currentSortOrder == AlbumSortOrder.ALBUM_A_Z
- sortOrderMenu.add(
- 0,
- R.id.action_album_sort_order_desc,
- 1,
- R.string.sort_order_z_a
- ).isChecked =
- currentSortOrder == AlbumSortOrder.ALBUM_Z_A
- sortOrderMenu.add(
- 0,
- R.id.action_album_sort_order_artist,
- 2,
- R.string.sort_order_artist
- ).isChecked =
- currentSortOrder == AlbumSortOrder.ALBUM_ARTIST
- sortOrderMenu.add(
- 0,
- R.id.action_album_sort_order_year,
- 3,
- R.string.sort_order_year
- ).isChecked =
- currentSortOrder == AlbumSortOrder.ALBUM_YEAR
+ navController.addOnDestinationChangedListener { _, destination, _ ->
+ if (destination.id == navGraph.startDestinationId) {
+ currentFragment(R.id.fragment_container)?.enterTransition = null
}
- is ArtistsFragment -> {
- sortOrderMenu.add(
- 0,
- R.id.action_artist_sort_order_asc,
- 0,
- R.string.sort_order_a_z
- ).isChecked =
- currentSortOrder == ArtistSortOrder.ARTIST_A_Z
- sortOrderMenu.add(
- 0,
- R.id.action_artist_sort_order_desc,
- 1,
- R.string.sort_order_z_a
- ).isChecked =
- currentSortOrder == ArtistSortOrder.ARTIST_Z_A
- }
- is SongsFragment -> {
- sortOrderMenu.add(
- 0,
- R.id.action_song_sort_order_asc,
- 0,
- R.string.sort_order_a_z
- ).isChecked =
- currentSortOrder == SongSortOrder.SONG_A_Z
- sortOrderMenu.add(
- 0,
- R.id.action_song_sort_order_desc,
- 1,
- R.string.sort_order_z_a
- ).isChecked =
- currentSortOrder == SongSortOrder.SONG_Z_A
- sortOrderMenu.add(
- 0,
- R.id.action_song_sort_order_artist,
- 2,
- R.string.sort_order_artist
- ).isChecked =
- currentSortOrder == SongSortOrder.SONG_ARTIST
- sortOrderMenu.add(
- 0,
- R.id.action_song_sort_order_album,
- 3,
- R.string.sort_order_album
- ).isChecked =
- currentSortOrder == SongSortOrder.SONG_ALBUM
- sortOrderMenu.add(
- 0,
- R.id.action_song_sort_order_year,
- 4,
- R.string.sort_order_year
- ).isChecked =
- currentSortOrder == SongSortOrder.SONG_YEAR
- sortOrderMenu.add(
- 0,
- R.id.action_song_sort_order_date,
- 5,
- R.string.sort_order_date
- ).isChecked =
- currentSortOrder == SongSortOrder.SONG_DATE
- sortOrderMenu.add(
- 0,
- R.id.action_song_sort_order_date_modified,
- 6,
- R.string.sort_order_date_modified
- ).isChecked = currentSortOrder == SongSortOrder.SONG_DATE_MODIFIED
- sortOrderMenu.add(
- 0,
- R.id.action_song_sort_order_composer,
- 7,
- R.string.sort_order_composer
- ).isChecked = currentSortOrder == SongSortOrder.COMPOSER
- }
- }
- sortOrderMenu.setGroupCheckable(0, true, true)
- }
-
- private fun getCurrentFragment(): Fragment? {
- return supportFragmentManager.findFragmentById(R.id.fragment_container)
- }
-
- private fun isFolderPage(): Boolean {
- return supportFragmentManager.findFragmentByTag(FoldersFragment.TAG) is FoldersFragment
- }
-
- private fun isHomePage(): Boolean {
- return supportFragmentManager.findFragmentByTag(BannerHomeFragment.TAG) is BannerHomeFragment
- }
-
- private fun isPlaylistPage(): Boolean {
- return supportFragmentManager.findFragmentByTag(PlaylistsFragment.TAG) is PlaylistsFragment
- }
-
- fun addOnAppBarOffsetChangedListener(
- changedListener: AppBarLayout.OnOffsetChangedListener
- ) {
- appBarLayout.addOnOffsetChangedListener(changedListener)
- }
-
- fun removeOnAppBarOffsetChangedListener(
- changedListener: AppBarLayout.OnOffsetChangedListener
- ) {
- appBarLayout.removeOnOffsetChangedListener(changedListener)
- }
-
- fun getTotalAppBarScrollingRange(): Int {
- return appBarLayout.totalScrollRange
- }
-
- override fun requestPermissions() {
- if (!blockRequestPermissions) {
- super.requestPermissions()
- }
- }
-
- override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
- super.onActivityResult(requestCode, resultCode, data)
- if (!hasPermissions()) {
- requestPermissions()
- }
- }
-
- private fun setupToolbar() {
- toolbar.setBackgroundColor(resolveColor(this, R.attr.colorSurface))
- appBarLayout.setBackgroundColor(resolveColor(this, R.attr.colorSurface))
- setSupportActionBar(toolbar)
- }
-
- private fun checkUpdate() {
- appUpdateManager = AppUpdateManagerFactory.create(this)
- appUpdateManager?.registerListener(listener)
-
- val appUpdateInfoTask: Task? = appUpdateManager?.appUpdateInfo
- appUpdateInfoTask?.addOnSuccessListener { appUpdateInfo ->
- if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
- && appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)
- ) {
- try {
- appUpdateManager?.startUpdateFlowForResult(
- appUpdateInfo,
- AppUpdateType.IMMEDIATE,
- this,
- APP_UPDATE_REQUEST_CODE
- )
- } catch (e: SendIntentException) {
- e.printStackTrace()
+ when (destination.id) {
+ R.id.action_home, R.id.action_song, R.id.action_album, R.id.action_artist, R.id.action_folder, R.id.action_playlist, R.id.action_genre, R.id.action_search -> {
+ // Save the last tab
+ if (PreferenceUtil.rememberLastTab) {
+ saveTab(destination.id)
+ }
+ // Show Bottom Navigation Bar
+ setBottomNavVisibility(visible = true, animate = true)
}
+ R.id.playing_queue_fragment -> {
+ setBottomNavVisibility(visible = false, hideBottomSheet = true)
+ }
+ else -> setBottomNavVisibility(
+ visible = false,
+ animate = true
+ ) // Hide Bottom Navigation Bar
}
}
}
- private fun popupSnackBarForCompleteUpdate() {
- val snackBar =
- Snackbar.make(
- findViewById(R.id.mainContent),
- "New app is ready!",
- Snackbar.LENGTH_INDEFINITE
- )
- snackBar.setAction(
- "Install"
- ) {
- appUpdateManager?.completeUpdate()
- }
- snackBar.setActionTextColor(accentColor(this))
- snackBar.show()
- }
-
- private fun setCurrentFragment(
- fragment: Fragment,
- tag: String
- ) {
- supportFragmentManager.commit {
- replace(R.id.fragment_container, fragment, tag)
- }
- currentFragment = fragment as MainActivityFragmentCallbacks
- }
-
- private fun selectedFragment(itemId: Int) {
- when (itemId) {
- R.id.action_album -> setCurrentFragment(
- AlbumsFragment.newInstance(),
- AlbumsFragment.TAG
- )
- R.id.action_artist -> setCurrentFragment(
- ArtistsFragment.newInstance(),
- ArtistsFragment.TAG
- )
- R.id.action_playlist -> setCurrentFragment(
- PlaylistsFragment.newInstance(),
- PlaylistsFragment.TAG
- )
- R.id.action_genre -> setCurrentFragment(
- GenresFragment.newInstance(),
- GenresFragment.TAG
- )
- R.id.action_playing_queue -> setCurrentFragment(
- PlayingQueueFragment.newInstance(),
- PlayingQueueFragment.TAG
- )
- R.id.action_song -> setCurrentFragment(
- SongsFragment.newInstance(),
- SongsFragment.TAG
- )
- R.id.action_folder -> setCurrentFragment(
- FoldersFragment.newInstance(this),
- FoldersFragment.TAG
- )
- R.id.action_home -> setCurrentFragment(
- BannerHomeFragment.newInstance(),
- BannerHomeFragment.TAG
- )
- else -> setCurrentFragment(
- BannerHomeFragment.newInstance(),
- BannerHomeFragment.TAG
- )
+ private fun saveTab(id: Int) {
+ if (PreferenceUtil.libraryCategory.firstOrNull { it.category.id == id }?.visible == true) {
+ PreferenceUtil.lastTab = id
}
}
- private fun restoreCurrentFragment() {
- val fragment = supportFragmentManager.findFragmentById(R.id.fragment_container)
- if (fragment != null) {
- currentFragment = fragment as MainActivityFragmentCallbacks
- }
- }
+ override fun onSupportNavigateUp(): Boolean =
+ findNavController(R.id.fragment_container).navigateUp()
- override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
- if (key == GENERAL_THEME || key == BLACK_THEME || key == ADAPTIVE_COLOR_APP || key == USER_NAME || key == TOGGLE_FULL_SCREEN || key == TOGGLE_VOLUME || key == ROUND_CORNERS || key == CAROUSEL_EFFECT || key == NOW_PLAYING_SCREEN_ID || key == TOGGLE_GENRE || key == BANNER_IMAGE_PATH || key == PROFILE_IMAGE_PATH || key == CIRCULAR_ALBUM_ART || key == KEEP_SCREEN_ON || key == TOGGLE_SEPARATE_LINE || key == TOGGLE_HOME_BANNER || key == TOGGLE_ADD_CONTROLS || key == ALBUM_COVER_STYLE || key == HOME_ARTIST_GRID_STYLE || key == ALBUM_COVER_TRANSFORM || key == DESATURATED_COLOR || key == EXTRA_SONG_INFO || key == TAB_TEXT_MODE || key == LANGUAGE_NAME || key == LIBRARY_CATEGORIES
- ) {
- postRecreate()
+ override fun onNewIntent(intent: Intent?) {
+ super.onNewIntent(intent)
+ val expand = intent?.extra(EXPAND_PANEL)?.value ?: false
+ if (expand && PreferenceUtil.isExpandPanel) {
+ fromNotification = true
+ slidingPanel.bringToFront()
+ expandPanel()
+ intent?.removeExtra(EXPAND_PANEL)
}
}
override fun onServiceConnected() {
super.onServiceConnected()
+ intent ?: return
handlePlaybackIntent(intent)
}
- private fun handlePlaybackIntent(intent: Intent?) {
- if (intent == null) {
- return
- }
- val uri = intent.data
- val mimeType = intent.type
- var handled = false
- if (intent.action != null && (intent.action == MediaStore.INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH)
- ) {
- val songs: List =
- getSongs(this, intent.extras!!)
- if (shuffleMode == MusicService.SHUFFLE_MODE_SHUFFLE) {
- openAndShuffleQueue(songs, true)
- } else {
- openQueue(songs, 0, true)
- }
- handled = true
- }
- if (uri != null && uri.toString().isNotEmpty()) {
- playFromUri(uri)
- handled = true
- } else if (MediaStore.Audio.Playlists.CONTENT_TYPE == mimeType) {
- val id = parseIdFromIntent(intent, "playlistId", "playlist").toInt()
- if (id >= 0) {
- val position = intent.getIntExtra("position", 0)
- val songs: List =
- ArrayList(getPlaylistSongList(this, id))
- openQueue(songs, position, true)
+ private fun handlePlaybackIntent(intent: Intent) {
+ lifecycleScope.launch(IO) {
+ val uri: Uri? = intent.data
+ val mimeType: String? = intent.type
+ var handled = false
+ if (intent.action != null &&
+ intent.action == MediaStore.INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH
+ ) {
+ val songs: List = getSongs(intent.extras!!)
+ if (MusicPlayerRemote.shuffleMode == MusicService.SHUFFLE_MODE_SHUFFLE) {
+ MusicPlayerRemote.openAndShuffleQueue(songs, true)
+ } else {
+ MusicPlayerRemote.openQueue(songs, 0, true)
+ }
handled = true
}
- } else if (MediaStore.Audio.Albums.CONTENT_TYPE == mimeType) {
- val id = parseIdFromIntent(intent, "albumId", "album").toInt()
- if (id >= 0) {
- val position = intent.getIntExtra("position", 0)
- openQueue(getAlbum(this, id).songs!!, position, true)
+ if (uri != null && uri.toString().isNotEmpty()) {
+ MusicPlayerRemote.playFromUri(this@MainActivity, uri)
handled = true
+ } else if (MediaStore.Audio.Playlists.CONTENT_TYPE == mimeType) {
+ val id = parseLongFromIntent(intent, "playlistId", "playlist")
+ if (id >= 0L) {
+ val position: Int = intent.getIntExtra("position", 0)
+ val songs: List = PlaylistSongsLoader.getPlaylistSongList(get(), id)
+ MusicPlayerRemote.openQueue(songs, position, true)
+ handled = true
+ }
+ } else if (MediaStore.Audio.Albums.CONTENT_TYPE == mimeType) {
+ val id = parseLongFromIntent(intent, "albumId", "album")
+ if (id >= 0L) {
+ val position: Int = intent.getIntExtra("position", 0)
+ val songs = libraryViewModel.albumById(id).songs
+ MusicPlayerRemote.openQueue(
+ songs,
+ position,
+ true
+ )
+ handled = true
+ }
+ } else if (MediaStore.Audio.Artists.CONTENT_TYPE == mimeType) {
+ val id = parseLongFromIntent(intent, "artistId", "artist")
+ if (id >= 0L) {
+ val position: Int = intent.getIntExtra("position", 0)
+ val songs: List = libraryViewModel.artistById(id).songs
+ MusicPlayerRemote.openQueue(
+ songs,
+ position,
+ true
+ )
+ handled = true
+ }
}
- } else if (MediaStore.Audio.Artists.CONTENT_TYPE == mimeType) {
- val id = parseIdFromIntent(intent, "artistId", "artist").toInt()
- if (id >= 0) {
- val position = intent.getIntExtra("position", 0)
- openQueue(getArtist(this, id).songs, position, true)
- handled = true
+ if (handled) {
+ setIntent(Intent())
}
}
- if (handled) {
- setIntent(Intent())
- }
}
- private fun parseIdFromIntent(
- intent: Intent, longKey: String,
- stringKey: String
+ private fun parseLongFromIntent(
+ intent: Intent,
+ longKey: String,
+ stringKey: String,
): Long {
var id = intent.getLongExtra(longKey, -1)
if (id < 0) {
@@ -750,37 +205,10 @@ class MainActivity : AbsSlidingMusicPanelActivity(),
try {
id = idString.toLong()
} catch (e: NumberFormatException) {
- Log.e(TAG, e.message)
+ logE(e)
}
}
}
return id
}
-
- override fun handleBackPress(): Boolean {
- if (cab != null && cab!!.isActive) {
- cab?.finish()
- return true
- }
- return super.handleBackPress() || currentFragment.handleBackPress()
- }
-
- override fun openCab(menuRes: Int, callback: MaterialCab.Callback): MaterialCab {
- cab?.let {
- if (it.isActive) it.finish()
- }
- cab = MaterialCab(this, R.id.cab_stub)
- .setMenu(menuRes)
- .setCloseDrawableRes(R.drawable.ic_close_white_24dp)
- .setBackgroundColor(
- RetroColorUtil.shiftBackgroundColorForLightText(
- ATHUtil.resolveColor(
- this,
- R.attr.colorSurface
- )
- )
- )
- .start(callback)
- return cab as MaterialCab
- }
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/PermissionActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/PermissionActivity.kt
new file mode 100644
index 000000000..5cb64cf93
--- /dev/null
+++ b/app/src/main/java/code/name/monkey/retromusic/activities/PermissionActivity.kt
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2020 Hemanth Savarla.
+ *
+ * Licensed under the GNU General Public License v3
+ *
+ * This is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ */
+package code.name.monkey.retromusic.activities
+
+import android.Manifest.permission.BLUETOOTH_CONNECT
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.content.res.ColorStateList
+import android.os.Build
+import android.os.Bundle
+import android.provider.Settings
+import androidx.activity.OnBackPressedCallback
+import androidx.annotation.RequiresApi
+import androidx.core.app.ActivityCompat
+import androidx.core.net.toUri
+import androidx.core.text.parseAsHtml
+import androidx.core.view.isVisible
+import code.name.monkey.appthemehelper.util.VersionUtils
+import code.name.monkey.retromusic.R
+import code.name.monkey.retromusic.activities.base.AbsMusicServiceActivity
+import code.name.monkey.retromusic.databinding.ActivityPermissionBinding
+import code.name.monkey.retromusic.extensions.*
+
+class PermissionActivity : AbsMusicServiceActivity() {
+ private lateinit var binding: ActivityPermissionBinding
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = ActivityPermissionBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+ setStatusBarColorAuto()
+ setTaskDescriptionColorAuto()
+ setupTitle()
+
+ binding.storagePermission.setButtonClick {
+ requestPermissions()
+ }
+ if (VersionUtils.hasMarshmallow()) {
+ binding.audioPermission.show()
+ binding.audioPermission.setButtonClick {
+ if (!hasAudioPermission()) {
+ val intent = Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS)
+ intent.data = ("package:" + applicationContext.packageName).toUri()
+ startActivity(intent)
+ }
+ }
+ }
+
+ if (VersionUtils.hasS()) {
+ binding.bluetoothPermission.show()
+ binding.bluetoothPermission.setButtonClick {
+ ActivityCompat.requestPermissions(
+ this,
+ arrayOf(BLUETOOTH_CONNECT),
+ BLUETOOTH_PERMISSION_REQUEST
+ )
+ }
+ } else {
+ binding.audioPermission.setNumber("2")
+ }
+
+ binding.finish.accentBackgroundColor()
+ binding.finish.setOnClickListener {
+ if (hasPermissions()) {
+ startActivity(
+ Intent(this, MainActivity::class.java).addFlags(
+ Intent.FLAG_ACTIVITY_NEW_TASK or
+ Intent.FLAG_ACTIVITY_CLEAR_TASK
+ )
+ )
+ finish()
+ }
+ }
+ onBackPressedDispatcher.addCallback(object : OnBackPressedCallback(true) {
+ override fun handleOnBackPressed() {
+ finishAffinity()
+ remove()
+ }
+ })
+ }
+
+ private fun setupTitle() {
+ val appName =
+ getString(
+ R.string.message_welcome,
+ "Metro "
+ )
+ .parseAsHtml()
+ binding.appNameText.text = appName
+ }
+
+ override fun onResume() {
+ super.onResume()
+ binding.finish.isEnabled = hasStoragePermission()
+ if (hasStoragePermission()) {
+ binding.storagePermission.checkImage.isVisible = true
+ binding.storagePermission.checkImage.imageTintList =
+ ColorStateList.valueOf(accentColor())
+ }
+ if (VersionUtils.hasMarshmallow()) {
+ if (hasAudioPermission()) {
+ binding.audioPermission.checkImage.isVisible = true
+ binding.audioPermission.checkImage.imageTintList =
+ ColorStateList.valueOf(accentColor())
+ }
+ }
+ if (VersionUtils.hasS()) {
+ if (hasBluetoothPermission()) {
+ binding.bluetoothPermission.checkImage.isVisible = true
+ binding.bluetoothPermission.checkImage.imageTintList =
+ ColorStateList.valueOf(accentColor())
+ }
+ }
+ }
+
+ private fun hasStoragePermission(): Boolean {
+ return hasPermissions()
+ }
+
+ @RequiresApi(Build.VERSION_CODES.S)
+ private fun hasBluetoothPermission(): Boolean {
+ return ActivityCompat.checkSelfPermission(
+ this,
+ BLUETOOTH_CONNECT
+ ) == PackageManager.PERMISSION_GRANTED
+ }
+
+ @RequiresApi(Build.VERSION_CODES.M)
+ private fun hasAudioPermission(): Boolean {
+ return Settings.System.canWrite(this)
+ }
+}
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/PlayingQueueActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/PlayingQueueActivity.kt
deleted file mode 100644
index ef9ffbe31..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/activities/PlayingQueueActivity.kt
+++ /dev/null
@@ -1,187 +0,0 @@
-package code.name.monkey.retromusic.activities
-
-import android.content.res.ColorStateList
-import android.os.Bundle
-import android.view.MenuItem
-import androidx.recyclerview.widget.LinearLayoutManager
-import androidx.recyclerview.widget.RecyclerView
-import code.name.monkey.appthemehelper.util.ColorUtil
-import code.name.monkey.appthemehelper.util.MaterialValueHelper
-import code.name.monkey.retromusic.R
-import code.name.monkey.retromusic.activities.base.AbsMusicServiceActivity
-import code.name.monkey.retromusic.adapter.song.PlayingQueueAdapter
-import code.name.monkey.retromusic.extensions.accentColor
-import code.name.monkey.retromusic.extensions.surfaceColor
-import code.name.monkey.retromusic.helper.MusicPlayerRemote
-import code.name.monkey.retromusic.util.MusicUtil
-import com.h6ah4i.android.widget.advrecyclerview.animator.DraggableItemAnimator
-import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager
-import com.h6ah4i.android.widget.advrecyclerview.swipeable.RecyclerViewSwipeManager
-import com.h6ah4i.android.widget.advrecyclerview.touchguard.RecyclerViewTouchActionGuardManager
-import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils
-import kotlinx.android.synthetic.main.activity_playing_queue.*
-
-open class PlayingQueueActivity : AbsMusicServiceActivity() {
-
- private var wrappedAdapter: RecyclerView.Adapter<*>? = null
- private var recyclerViewDragDropManager: RecyclerViewDragDropManager? = null
- private var recyclerViewSwipeManager: RecyclerViewSwipeManager? = null
- private var recyclerViewTouchActionGuardManager: RecyclerViewTouchActionGuardManager? = null
- private var playingQueueAdapter: PlayingQueueAdapter? = null
- private lateinit var linearLayoutManager: LinearLayoutManager
-
- private fun getUpNextAndQueueTime(): String {
- val duration = MusicPlayerRemote.getQueueDurationMillis(MusicPlayerRemote.position)
- return MusicUtil.buildInfoString(
- resources.getString(R.string.up_next),
- MusicUtil.getReadableDurationString(duration)
- )
- }
-
- override fun onCreate(savedInstanceState: Bundle?) {
- setDrawUnderStatusBar()
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_playing_queue)
- setStatusbarColorAuto()
- setNavigationbarColorAuto()
- setTaskDescriptionColorAuto()
- setLightNavigationBar(true)
-
- setupToolbar()
- setUpRecyclerView()
-
- clearQueue.setOnClickListener {
- MusicPlayerRemote.clearQueue()
- }
- checkForPadding()
- }
-
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- return when (item.itemId) {
- android.R.id.home -> {
- onBackPressed()
- true
- }
- else -> super.onOptionsItemSelected(item)
- }
- }
-
- private fun setUpRecyclerView() {
- recyclerViewTouchActionGuardManager = RecyclerViewTouchActionGuardManager()
- recyclerViewDragDropManager = RecyclerViewDragDropManager()
- recyclerViewSwipeManager = RecyclerViewSwipeManager()
-
- val animator = DraggableItemAnimator()
- animator.supportsChangeAnimations = false
-
- playingQueueAdapter = PlayingQueueAdapter(
- this,
- MusicPlayerRemote.playingQueue.toMutableList(),
- MusicPlayerRemote.position,
- R.layout.item_queue
- )
- wrappedAdapter = recyclerViewDragDropManager?.createWrappedAdapter(playingQueueAdapter!!)
- wrappedAdapter = wrappedAdapter?.let { recyclerViewSwipeManager?.createWrappedAdapter(it) }
-
- linearLayoutManager = LinearLayoutManager(this)
-
- recyclerView.layoutManager = linearLayoutManager
- recyclerView.adapter = wrappedAdapter
- recyclerView.itemAnimator = animator
- recyclerViewTouchActionGuardManager?.attachRecyclerView(recyclerView)
- recyclerViewDragDropManager?.attachRecyclerView(recyclerView)
- recyclerViewSwipeManager?.attachRecyclerView(recyclerView)
- linearLayoutManager.scrollToPositionWithOffset(MusicPlayerRemote.position + 1, 0)
-
- recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
- override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
- super.onScrolled(recyclerView, dx, dy)
- if (dy > 0) {
- clearQueue.shrink()
- } else if (dy < 0) {
- clearQueue.extend()
- }
- }
- })
- //ViewUtil.setUpFastScrollRecyclerViewColor(this, recyclerView)
- }
-
- private fun checkForPadding() {
- }
-
- override fun onQueueChanged() {
- if (MusicPlayerRemote.playingQueue.isEmpty()) {
- finish()
- return
- }
- checkForPadding()
- updateQueue()
- updateCurrentSong()
- }
-
- override fun onMediaStoreChanged() {
- updateQueue()
- updateCurrentSong()
- }
-
- private fun updateCurrentSong() {
- toolbar.subtitle = getUpNextAndQueueTime()
- }
-
- override fun onPlayingMetaChanged() {
- updateQueuePosition()
- }
-
- private fun updateQueuePosition() {
- playingQueueAdapter?.setCurrent(MusicPlayerRemote.position)
- resetToCurrentPosition()
- toolbar.subtitle = getUpNextAndQueueTime()
- }
-
- private fun updateQueue() {
- playingQueueAdapter?.swapDataSet(MusicPlayerRemote.playingQueue, MusicPlayerRemote.position)
- resetToCurrentPosition()
- }
-
- private fun resetToCurrentPosition() {
- recyclerView.stopScroll()
- linearLayoutManager.scrollToPositionWithOffset(MusicPlayerRemote.position + 1, 0)
- }
-
- override fun onPause() {
- if (recyclerViewDragDropManager != null) {
- recyclerViewDragDropManager!!.cancelDrag()
- }
- super.onPause()
- }
-
- override fun onDestroy() {
- if (recyclerViewDragDropManager != null) {
- recyclerViewDragDropManager!!.release()
- recyclerViewDragDropManager = null
- }
- if (recyclerViewSwipeManager != null) {
- recyclerViewSwipeManager?.release()
- recyclerViewSwipeManager = null
- }
- if (wrappedAdapter != null) {
- WrapperAdapterUtils.releaseAll(wrappedAdapter)
- wrappedAdapter = null
- }
- playingQueueAdapter = null
- super.onDestroy()
- }
-
- private fun setupToolbar() {
- toolbar.subtitle = getUpNextAndQueueTime()
- toolbar.setBackgroundColor(surfaceColor())
- setSupportActionBar(toolbar)
- clearQueue.backgroundTintList = ColorStateList.valueOf(accentColor())
- ColorStateList.valueOf(
- MaterialValueHelper.getPrimaryTextColor(this, ColorUtil.isColorLight(accentColor()))
- ).apply {
- clearQueue.setTextColor(this)
- clearQueue.iconTint = this
- }
- }
-}
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/PlaylistDetailActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/PlaylistDetailActivity.kt
deleted file mode 100644
index 6ef54ffe9..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/activities/PlaylistDetailActivity.kt
+++ /dev/null
@@ -1,245 +0,0 @@
-package code.name.monkey.retromusic.activities
-
-import android.os.Bundle
-import android.view.Menu
-import android.view.MenuItem
-import android.view.View
-import androidx.recyclerview.widget.LinearLayoutManager
-import androidx.recyclerview.widget.RecyclerView
-import code.name.monkey.appthemehelper.util.ATHUtil
-import code.name.monkey.retromusic.App
-import code.name.monkey.retromusic.R
-import code.name.monkey.retromusic.activities.base.AbsSlidingMusicPanelActivity
-import code.name.monkey.retromusic.adapter.song.OrderablePlaylistSongAdapter
-import code.name.monkey.retromusic.adapter.song.PlaylistSongAdapter
-import code.name.monkey.retromusic.adapter.song.SongAdapter
-import code.name.monkey.retromusic.extensions.applyToolbar
-import code.name.monkey.retromusic.helper.menu.PlaylistMenuHelper
-import code.name.monkey.retromusic.interfaces.CabHolder
-import code.name.monkey.retromusic.loaders.PlaylistLoader
-import code.name.monkey.retromusic.model.AbsCustomPlaylist
-import code.name.monkey.retromusic.model.Playlist
-import code.name.monkey.retromusic.model.Song
-import code.name.monkey.retromusic.mvp.presenter.PlaylistSongsPresenter
-import code.name.monkey.retromusic.mvp.presenter.PlaylistSongsView
-import code.name.monkey.retromusic.util.DensityUtil
-import code.name.monkey.retromusic.util.PlaylistsUtil
-import code.name.monkey.retromusic.util.RetroColorUtil
-import com.afollestad.materialcab.MaterialCab
-import com.h6ah4i.android.widget.advrecyclerview.animator.RefactoredDefaultItemAnimator
-import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager
-import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils
-import kotlinx.android.synthetic.main.activity_playlist_detail.*
-import javax.inject.Inject
-
-class PlaylistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder, PlaylistSongsView {
-
- @Inject
- lateinit var playlistSongsPresenter: PlaylistSongsPresenter
-
- private lateinit var playlist: Playlist
- private var cab: MaterialCab? = null
- private lateinit var adapter: SongAdapter
- private var wrappedAdapter: RecyclerView.Adapter<*>? = null
- private var recyclerViewDragDropManager: RecyclerViewDragDropManager? = null
-
- override fun onCreate(savedInstanceState: Bundle?) {
- setDrawUnderStatusBar()
- super.onCreate(savedInstanceState)
- setStatusbarColorAuto()
- setNavigationbarColorAuto()
- setTaskDescriptionColorAuto()
- setLightNavigationBar(true)
- setBottomBarVisibility(View.GONE)
-
- App.musicComponent.inject(this)
- playlistSongsPresenter.attachView(this)
-
- if (intent.extras != null) {
- playlist = intent.extras!!.getParcelable(EXTRA_PLAYLIST)!!
- } else {
- finish()
- }
-
- setUpToolBar()
- setUpRecyclerView()
- }
-
- override fun createContentView(): View {
- return wrapSlidingMusicPanel(R.layout.activity_playlist_detail)
- }
-
- private fun setUpRecyclerView() {
-
- recyclerView.layoutManager = LinearLayoutManager(this)
- if (playlist is AbsCustomPlaylist) {
- adapter = PlaylistSongAdapter(this, ArrayList(), R.layout.item_list, this)
- recyclerView.adapter = adapter
- } else {
- recyclerViewDragDropManager = RecyclerViewDragDropManager()
- val animator = RefactoredDefaultItemAnimator()
- adapter = OrderablePlaylistSongAdapter(this,
- ArrayList(),
- R.layout.item_list,
- this,
- object : OrderablePlaylistSongAdapter.OnMoveItemListener {
- override fun onMoveItem(fromPosition: Int, toPosition: Int) {
- if (PlaylistsUtil.moveItem(
- this@PlaylistDetailActivity,
- playlist.id,
- fromPosition,
- toPosition
- )
- ) {
- val song = adapter.dataSet.removeAt(fromPosition)
- adapter.dataSet.add(toPosition, song)
- adapter.notifyItemMoved(fromPosition, toPosition)
- }
- }
- })
- wrappedAdapter = recyclerViewDragDropManager!!.createWrappedAdapter(adapter)
-
- recyclerView.adapter = wrappedAdapter
- recyclerView.itemAnimator = animator
-
- recyclerViewDragDropManager?.attachRecyclerView(recyclerView)
- }
- adapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
- override fun onChanged() {
- super.onChanged()
- checkIsEmpty()
- }
- })
- }
-
- override fun onResume() {
- super.onResume()
- playlistSongsPresenter.loadPlaylistSongs(playlist)
- }
-
- private fun setUpToolBar() {
- applyToolbar(toolbar)
- title = playlist.name
- }
-
- override fun onCreateOptionsMenu(menu: Menu): Boolean {
- menuInflater.inflate(
- if (playlist is AbsCustomPlaylist) R.menu.menu_smart_playlist_detail
- else R.menu.menu_playlist_detail, menu
- )
- return super.onCreateOptionsMenu(menu)
- }
-
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- when (item.itemId) {
- android.R.id.home -> {
- onBackPressed()
- return true
- }
- }
- return PlaylistMenuHelper.handleMenuClick(this, playlist, item)
- }
-
- override fun openCab(menuRes: Int, callback: MaterialCab.Callback): MaterialCab {
- if (cab != null && cab!!.isActive) {
- cab!!.finish()
- }
- cab = MaterialCab(this, R.id.cab_stub).setMenu(menuRes)
- .setCloseDrawableRes(R.drawable.ic_close_white_24dp)
- .setBackgroundColor(
- RetroColorUtil.shiftBackgroundColorForLightText(
- ATHUtil.resolveColor(
- this,
- R.attr.colorSurface
- )
- )
- ).start(callback)
- return cab!!
- }
-
- override fun onBackPressed() {
- if (cab != null && cab!!.isActive) {
- cab!!.finish()
- } else {
- recyclerView!!.stopScroll()
- super.onBackPressed()
- }
- }
-
- override fun onMediaStoreChanged() {
- super.onMediaStoreChanged()
- if (playlist !is AbsCustomPlaylist) {
- // Playlist deleted
- if (!PlaylistsUtil.doesPlaylistExist(this, playlist.id)) {
- finish()
- return
- }
- // Playlist renamed
- val playlistName = PlaylistsUtil.getNameForPlaylist(this, playlist.id.toLong())
- if (playlistName != playlist.name) {
- playlist = PlaylistLoader.getPlaylist(this, playlist.id)
- setToolbarTitle(playlist.name)
- }
- }
- playlistSongsPresenter.loadPlaylistSongs(playlist)
- }
-
- private fun setToolbarTitle(title: String) {
- supportActionBar?.title = title
- }
-
- private fun checkForPadding() {
- val height = DensityUtil.dip2px(this, 52f)
- recyclerView.setPadding(0, 0, 0, (height))
- }
-
- private fun checkIsEmpty() {
- checkForPadding()
- emptyEmoji.text = getEmojiByUnicode(0x1F631)
- empty.visibility = if (adapter.itemCount == 0) View.VISIBLE else View.GONE
- emptyText.visibility = if (adapter.itemCount == 0) View.VISIBLE else View.GONE
- }
-
- private fun getEmojiByUnicode(unicode: Int): String {
- return String(Character.toChars(unicode))
- }
-
- public override fun onPause() {
- if (recyclerViewDragDropManager != null) {
- recyclerViewDragDropManager!!.cancelDrag()
- }
- super.onPause()
- }
-
- override fun onDestroy() {
- if (recyclerViewDragDropManager != null) {
- recyclerViewDragDropManager!!.release()
- recyclerViewDragDropManager = null
- }
-
- if (recyclerView != null) {
- recyclerView!!.itemAnimator = null
- recyclerView!!.adapter = null
- }
-
- if (wrappedAdapter != null) {
- WrapperAdapterUtils.releaseAll(wrappedAdapter)
- wrappedAdapter = null
- }
- super.onDestroy()
- playlistSongsPresenter.detachView()
- }
-
- override fun showEmptyView() {
- empty.visibility = View.VISIBLE
- emptyText.visibility = View.VISIBLE
- }
-
- override fun songs(songs: List) {
- adapter.swapDataSet(songs)
- }
-
- companion object {
- var EXTRA_PLAYLIST = "extra_playlist"
- }
-}
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/PurchaseActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/PurchaseActivity.kt
deleted file mode 100644
index 20f187498..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/activities/PurchaseActivity.kt
+++ /dev/null
@@ -1,159 +0,0 @@
-package code.name.monkey.retromusic.activities
-
-import android.content.Intent
-import android.content.res.ColorStateList
-import android.graphics.Color
-import android.os.AsyncTask
-import android.os.Bundle
-import android.util.Log
-import android.view.MenuItem
-import android.widget.Toast
-import code.name.monkey.appthemehelper.ThemeStore
-import code.name.monkey.appthemehelper.util.MaterialUtil
-import code.name.monkey.retromusic.App
-import code.name.monkey.retromusic.BuildConfig
-import code.name.monkey.retromusic.R
-import code.name.monkey.retromusic.activities.base.AbsBaseActivity
-import com.anjlab.android.iab.v3.BillingProcessor
-import com.anjlab.android.iab.v3.TransactionDetails
-import kotlinx.android.synthetic.main.activity_pro_version.*
-import java.lang.ref.WeakReference
-
-class PurchaseActivity : AbsBaseActivity(), BillingProcessor.IBillingHandler {
-
- private lateinit var billingProcessor: BillingProcessor
- private var restorePurchaseAsyncTask: AsyncTask<*, *, *>? = null
-
- override fun onCreate(savedInstanceState: Bundle?) {
- setDrawUnderStatusBar()
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_pro_version)
- setStatusbarColor(Color.TRANSPARENT)
- setLightStatusbar(false)
- setNavigationbarColor(Color.BLACK)
- setLightNavigationBar(false)
- toolbar.navigationIcon?.setTint(Color.WHITE)
- toolbar.setNavigationOnClickListener { onBackPressed() }
-
- restoreButton.isEnabled = false
- purchaseButton.isEnabled = false
-
- billingProcessor = BillingProcessor(this, BuildConfig.GOOGLE_PLAY_LICENSING_KEY, this)
-
- MaterialUtil.setTint(purchaseButton, true)
-
- restoreButton.setOnClickListener {
- if (restorePurchaseAsyncTask == null || restorePurchaseAsyncTask!!.status != AsyncTask.Status.RUNNING) {
- restorePurchase()
- }
-
- }
- purchaseButton.setOnClickListener {
- billingProcessor.purchase(this@PurchaseActivity, App.PRO_VERSION_PRODUCT_ID)
- }
- bannerContainer.backgroundTintList =
- ColorStateList.valueOf(ThemeStore.accentColor(this))
- }
-
- private fun restorePurchase() {
- if (restorePurchaseAsyncTask != null) {
- restorePurchaseAsyncTask!!.cancel(false)
- }
- restorePurchaseAsyncTask = RestorePurchaseAsyncTask(this).execute()
- }
-
- override fun onProductPurchased(productId: String, details: TransactionDetails?) {
- Toast.makeText(this, R.string.thank_you, Toast.LENGTH_SHORT).show()
- setResult(RESULT_OK)
- }
-
- override fun onPurchaseHistoryRestored() {
- if (App.isProVersion()) {
- Toast.makeText(
- this,
- R.string.restored_previous_purchase_please_restart,
- Toast.LENGTH_LONG
- ).show()
- setResult(RESULT_OK)
- } else {
- Toast.makeText(this, R.string.no_purchase_found, Toast.LENGTH_SHORT).show()
- }
- }
-
- override fun onBillingError(errorCode: Int, error: Throwable?) {
- Log.e(TAG, "Billing error: code = $errorCode", error)
- }
-
- override fun onBillingInitialized() {
- restoreButton.isEnabled = true
- purchaseButton.isEnabled = true
- }
-
- public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
- if (!billingProcessor.handleActivityResult(requestCode, resultCode, data)) {
- super.onActivityResult(requestCode, resultCode, data)
- }
- }
-
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- when (item.itemId) {
- android.R.id.home -> finish()
- }
- return super.onOptionsItemSelected(item)
- }
-
- override fun onDestroy() {
- billingProcessor.release()
- super.onDestroy()
- }
-
- private class RestorePurchaseAsyncTask internal constructor(purchaseActivity: PurchaseActivity) :
- AsyncTask() {
-
- private val buyActivityWeakReference: WeakReference = WeakReference(
- purchaseActivity
- )
-
- override fun onPreExecute() {
- super.onPreExecute()
- val purchaseActivity = buyActivityWeakReference.get()
- if (purchaseActivity != null) {
- Toast.makeText(purchaseActivity, R.string.restoring_purchase, Toast.LENGTH_SHORT)
- .show()
- } else {
- cancel(false)
- }
- }
-
- override fun doInBackground(vararg params: Void): Boolean? {
- val purchaseActivity = buyActivityWeakReference.get()
- if (purchaseActivity != null) {
- return purchaseActivity.billingProcessor.loadOwnedPurchasesFromGoogle()
- }
- cancel(false)
- return null
- }
-
- override fun onPostExecute(b: Boolean?) {
- super.onPostExecute(b)
- val purchaseActivity = buyActivityWeakReference.get()
- if (purchaseActivity == null || b == null) {
- return
- }
-
- if (b) {
- purchaseActivity.onPurchaseHistoryRestored()
- } else {
- Toast.makeText(
- purchaseActivity,
- R.string.could_not_restore_purchase,
- Toast.LENGTH_SHORT
- ).show()
- }
- }
- }
-
- companion object {
- private const val TAG: String = "PurchaseActivity"
- }
-}
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/SearchActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/SearchActivity.kt
deleted file mode 100644
index d198bd5ca..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/activities/SearchActivity.kt
+++ /dev/null
@@ -1,224 +0,0 @@
-package code.name.monkey.retromusic.activities
-
-import android.app.Activity
-import android.app.Service
-import android.content.ActivityNotFoundException
-import android.content.Intent
-import android.content.res.ColorStateList
-import android.os.Bundle
-import android.speech.RecognizerIntent
-import android.text.Editable
-import android.text.TextWatcher
-import android.view.View
-import android.view.inputmethod.InputMethodManager
-import android.widget.TextView.BufferType
-import android.widget.Toast
-import androidx.appcompat.widget.SearchView.OnQueryTextListener
-import androidx.recyclerview.widget.LinearLayoutManager
-import androidx.recyclerview.widget.RecyclerView
-import androidx.transition.TransitionManager
-import code.name.monkey.appthemehelper.ThemeStore
-import code.name.monkey.appthemehelper.util.ATHUtil
-import code.name.monkey.appthemehelper.util.ColorUtil
-import code.name.monkey.appthemehelper.util.MaterialValueHelper
-import code.name.monkey.retromusic.App
-import code.name.monkey.retromusic.R
-import code.name.monkey.retromusic.activities.base.AbsMusicServiceActivity
-import code.name.monkey.retromusic.adapter.SearchAdapter
-import code.name.monkey.retromusic.mvp.presenter.SearchPresenter
-import code.name.monkey.retromusic.mvp.presenter.SearchView
-import code.name.monkey.retromusic.util.RetroUtil
-import com.google.android.material.textfield.TextInputEditText
-import kotlinx.android.synthetic.main.activity_search.*
-import java.util.*
-import javax.inject.Inject
-import kotlin.collections.ArrayList
-
-class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatcher, SearchView {
- @Inject
- lateinit var searchPresenter: SearchPresenter
-
- private var searchAdapter: SearchAdapter? = null
- private var query: String? = null
-
- override fun onCreate(savedInstanceState: Bundle?) {
- setDrawUnderStatusBar()
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_search)
- setStatusbarColorAuto()
- setNavigationbarColorAuto()
- setTaskDescriptionColorAuto()
- setLightNavigationBar(true)
-
- App.musicComponent.inject(this)
- searchPresenter.attachView(this)
-
- setupRecyclerView()
- setUpToolBar()
- setupSearchView()
-
- if (intent.getBooleanExtra(EXTRA_SHOW_MIC, false)) {
- startMicSearch()
- }
-
- back.setOnClickListener { onBackPressed() }
- voiceSearch.setOnClickListener { startMicSearch() }
- clearText.setOnClickListener { searchView.clearText() }
- searchContainer.backgroundTintList =
- ColorStateList.valueOf(ATHUtil.resolveColor(this, R.attr.colorSurface))
-
- keyboardPopup.setOnClickListener {
- val inputManager = getSystemService(Service.INPUT_METHOD_SERVICE) as InputMethodManager
- inputManager.showSoftInput(searchView, InputMethodManager.SHOW_IMPLICIT)
- }
-
- keyboardPopup.backgroundTintList = ColorStateList.valueOf(ThemeStore.accentColor(this))
- ColorStateList.valueOf(
- MaterialValueHelper.getPrimaryTextColor(
- this,
- ColorUtil.isColorLight(ThemeStore.accentColor(this))
- )
- ).apply {
- keyboardPopup.setTextColor(this)
- keyboardPopup.iconTint = this
- }
- if (savedInstanceState != null) {
- query = savedInstanceState.getString(QUERY)
- }
- }
-
- private fun setupRecyclerView() {
- searchAdapter = SearchAdapter(this, emptyList())
- searchAdapter?.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
- override fun onChanged() {
- super.onChanged()
- empty.visibility = if (searchAdapter!!.itemCount < 1) View.VISIBLE else View.GONE
- }
- })
- recyclerView.apply {
- layoutManager = LinearLayoutManager(this@SearchActivity)
- adapter = searchAdapter
- }
- recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
- override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
- super.onScrolled(recyclerView, dx, dy)
- if (dy > 0) {
- keyboardPopup.shrink()
- } else if (dy < 0) {
- keyboardPopup.extend()
- }
- }
- })
- }
-
- private fun setupSearchView() {
- searchView.addTextChangedListener(this)
- }
-
- override fun onDestroy() {
- super.onDestroy()
- searchPresenter.detachView()
- }
-
- override fun onSaveInstanceState(outState: Bundle) {
- super.onSaveInstanceState(outState)
- outState.putString(QUERY, query)
- }
-
- private fun setUpToolBar() {
- title = null
- }
-
- private fun search(query: String) {
- this.query = query
- TransitionManager.beginDelayedTransition(appBarLayout)
- voiceSearch.visibility = if (query.isNotEmpty()) View.GONE else View.VISIBLE
- clearText.visibility = if (query.isNotEmpty()) View.VISIBLE else View.GONE
- searchPresenter.search(query)
- }
-
- override fun onMediaStoreChanged() {
- super.onMediaStoreChanged()
- query?.let { search(it) }
- }
-
- override fun onQueryTextSubmit(query: String): Boolean {
- hideSoftKeyboard()
- return false
- }
-
- override fun onQueryTextChange(newText: String): Boolean {
- search(newText)
- return false
- }
-
- private fun hideSoftKeyboard() {
- RetroUtil.hideSoftKeyboard(this@SearchActivity)
- if (searchView != null) {
- searchView.clearFocus()
- }
- }
-
- override fun showEmptyView() {
- searchAdapter?.swapDataSet(ArrayList())
- }
-
- override fun showData(data: MutableList) {
- searchAdapter?.swapDataSet(data)
- }
-
- override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
- super.onActivityResult(requestCode, resultCode, data)
- when (requestCode) {
- REQ_CODE_SPEECH_INPUT -> {
- if (resultCode == Activity.RESULT_OK && null != data) {
- val result: ArrayList? =
- data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS)
- query = result?.get(0)
- searchView.setText(query, BufferType.EDITABLE)
- searchPresenter.search(query!!)
- }
- }
- }
- }
-
- private fun startMicSearch() {
- val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
- intent.putExtra(
- RecognizerIntent.EXTRA_LANGUAGE_MODEL,
- RecognizerIntent.LANGUAGE_MODEL_FREE_FORM
- )
- intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault())
- intent.putExtra(RecognizerIntent.EXTRA_PROMPT, getString(R.string.speech_prompt))
- try {
- startActivityForResult(intent, REQ_CODE_SPEECH_INPUT)
- } catch (e: ActivityNotFoundException) {
- e.printStackTrace()
- Toast.makeText(this, getString(R.string.speech_not_supported), Toast.LENGTH_SHORT)
- .show()
- }
- }
-
- override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
- }
-
- override fun onTextChanged(newText: CharSequence, start: Int, before: Int, count: Int) {
- search(newText.toString())
- }
-
- override fun afterTextChanged(s: Editable) {
- }
-
- companion object {
- val TAG: String = SearchActivity::class.java.simpleName
-
- const val EXTRA_SHOW_MIC = "extra_show_mic"
- const val QUERY: String = "query"
-
- private const val REQ_CODE_SPEECH_INPUT = 9002
- }
-}
-
-fun TextInputEditText.clearText() {
- text = null
-}
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/SettingsActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/SettingsActivity.kt
deleted file mode 100755
index 241d59c4b..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/activities/SettingsActivity.kt
+++ /dev/null
@@ -1,91 +0,0 @@
-package code.name.monkey.retromusic.activities
-
-import android.os.Bundle
-import android.view.MenuItem
-import androidx.annotation.StringRes
-import androidx.fragment.app.Fragment
-import code.name.monkey.appthemehelper.ThemeStore
-import code.name.monkey.appthemehelper.util.VersionUtils
-import code.name.monkey.retromusic.R
-import code.name.monkey.retromusic.activities.base.AbsBaseActivity
-import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager
-import code.name.monkey.retromusic.extensions.applyToolbar
-import code.name.monkey.retromusic.fragments.settings.MainSettingsFragment
-import com.afollestad.materialdialogs.color.ColorChooserDialog
-import kotlinx.android.synthetic.main.activity_settings.*
-
-class SettingsActivity : AbsBaseActivity(), ColorChooserDialog.ColorCallback {
-
- private val fragmentManager = supportFragmentManager
-
- override fun onCreate(savedInstanceState: Bundle?) {
- setDrawUnderStatusBar()
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_settings)
- setStatusbarColorAuto()
- setNavigationbarColorAuto()
- setLightNavigationBar(true)
- setupToolbar()
-
- if (savedInstanceState == null) {
- fragmentManager.beginTransaction().replace(R.id.contentFrame, MainSettingsFragment())
- .commit()
- }
- }
-
- private fun setupToolbar() {
- setTitle(R.string.action_settings)
- applyToolbar(toolbar)
- }
-
- fun setupFragment(fragment: Fragment, @StringRes titleName: Int) {
- val fragmentTransaction = fragmentManager
- .beginTransaction()
- .setCustomAnimations(
- R.anim.sliding_in_left,
- R.anim.sliding_out_right,
- android.R.anim.slide_in_left,
- android.R.anim.slide_out_right
- )
- fragmentTransaction.replace(R.id.contentFrame, fragment, fragment.tag)
- fragmentTransaction.addToBackStack(null)
- fragmentTransaction.commit()
- setTitle(titleName)
- }
-
- override fun onBackPressed() {
- if (fragmentManager.backStackEntryCount == 0) {
- super.onBackPressed()
- } else {
- setTitle(R.string.action_settings)
- fragmentManager.popBackStack()
- }
- }
-
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- if (item.itemId == android.R.id.home) {
- onBackPressed()
- return true
- }
- return super.onOptionsItemSelected(item)
- }
-
- companion object {
- const val TAG: String = "SettingsActivity"
- }
-
- override fun onColorSelection(dialog: ColorChooserDialog, selectedColor: Int) {
- when (dialog.title) {
- R.string.accent_color -> {
- ThemeStore.editTheme(this).accentColor(selectedColor).commit()
- if (VersionUtils.hasNougatMR())
- DynamicShortcutManager(this).updateDynamicShortcuts()
- }
- }
- recreate()
- }
-
- override fun onColorChooserDismissed(dialog: ColorChooserDialog) {
-
- }
-}
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/ShareInstagramStory.kt b/app/src/main/java/code/name/monkey/retromusic/activities/ShareInstagramStory.kt
index 3b3f36049..546c9d794 100644
--- a/app/src/main/java/code/name/monkey/retromusic/activities/ShareInstagramStory.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/activities/ShareInstagramStory.kt
@@ -1,46 +1,51 @@
/*
- * Copyright (c) 2020 Hemanth Savarala.
+ * Copyright (c) 2020 Hemanth Savarla.
*
* Licensed under the GNU General Public License v3
*
- * This is free software: you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by
- * the Free Software Foundation either version 3 of the License, or (at your option) any later version.
+ * This is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
+ *
*/
-
package code.name.monkey.retromusic.activities
import android.content.res.ColorStateList
import android.graphics.Bitmap
import android.graphics.Color
import android.graphics.drawable.GradientDrawable
-import android.net.Uri
import android.os.Bundle
import android.provider.MediaStore.Images.Media
import android.view.MenuItem
+import androidx.core.net.toUri
+import androidx.core.os.BundleCompat
import androidx.core.view.drawToBitmap
-import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.MaterialValueHelper
-import code.name.monkey.retromusic.R
-import code.name.monkey.retromusic.activities.base.AbsBaseActivity
+import code.name.monkey.retromusic.activities.base.AbsThemeActivity
+import code.name.monkey.retromusic.databinding.ActivityShareInstagramBinding
+import code.name.monkey.retromusic.extensions.accentColor
+import code.name.monkey.retromusic.extensions.setStatusBarColor
+import code.name.monkey.retromusic.glide.RetroGlideExtension
+import code.name.monkey.retromusic.glide.RetroGlideExtension.asBitmapPalette
+import code.name.monkey.retromusic.glide.RetroGlideExtension.songCoverOptions
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
-import code.name.monkey.retromusic.glide.SongGlideRequest
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.Share
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.bumptech.glide.Glide
-import kotlinx.android.synthetic.main.activity_share_instagram.*
/**
* Created by hemanths on 2020-02-02.
*/
-class ShareInstagramStory : AbsBaseActivity() {
+class ShareInstagramStory : AbsThemeActivity() {
+
+ private lateinit var binding: ActivityShareInstagramBinding
companion object {
const val EXTRA_SONG = "extra_song"
@@ -48,76 +53,59 @@ class ShareInstagramStory : AbsBaseActivity() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == android.R.id.home) {
- onBackPressed()
+ onBackPressedDispatcher.onBackPressed()
return true
}
return super.onOptionsItemSelected(item)
}
override fun onCreate(savedInstanceState: Bundle?) {
- setDrawUnderStatusBar()
super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_share_instagram)
- setStatusbarColor(Color.TRANSPARENT)
- setNavigationbarColor(Color.BLACK)
+ binding = ActivityShareInstagramBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+ setStatusBarColor(Color.TRANSPARENT)
- toolbar.setBackgroundColor(Color.TRANSPARENT)
- setSupportActionBar(toolbar)
+ binding.toolbar.setBackgroundColor(Color.TRANSPARENT)
+ setSupportActionBar(binding.toolbar)
- val song = intent.extras?.getParcelable(EXTRA_SONG)
+ val song = intent.extras?.let { BundleCompat.getParcelable(it, EXTRA_SONG, Song::class.java) }
song?.let { songFinal ->
- SongGlideRequest.Builder.from(Glide.with(this), songFinal)
- .checkIgnoreMediaStore(this@ShareInstagramStory)
- .generatePalette(this@ShareInstagramStory)
- .build()
- .into(object : RetroMusicColoredTarget(image) {
+ Glide.with(this)
+ .asBitmapPalette()
+ .songCoverOptions(songFinal)
+ .load(RetroGlideExtension.getSongModel(songFinal))
+ .into(object : RetroMusicColoredTarget(binding.image) {
override fun onColorReady(colors: MediaNotificationProcessor) {
- val isColorLight = ColorUtil.isColorLight(colors.backgroundColor)
- setColors(isColorLight, colors.backgroundColor)
+ setColors(colors.backgroundColor)
}
})
- shareTitle.text = songFinal.title
- shareText.text = songFinal.artistName
- shareButton.setOnClickListener {
+ binding.shareTitle.text = songFinal.title
+ binding.shareText.text = songFinal.artistName
+ binding.shareButton.setOnClickListener {
val path: String = Media.insertImage(
contentResolver,
- mainContent.drawToBitmap(Bitmap.Config.ARGB_8888),
+ binding.mainContent.drawToBitmap(Bitmap.Config.ARGB_8888),
"Design", null
)
- val uri = Uri.parse(path)
Share.shareStoryToSocial(
this@ShareInstagramStory,
- uri
+ path.toUri()
)
}
}
- shareButton.setTextColor(
+ binding.shareButton.setTextColor(
MaterialValueHelper.getPrimaryTextColor(
this,
- ColorUtil.isColorLight(ThemeStore.accentColor(this))
+ ColorUtil.isColorLight(accentColor())
)
)
- shareButton.backgroundTintList = ColorStateList.valueOf(ThemeStore.accentColor(this))
+ binding.shareButton.backgroundTintList =
+ ColorStateList.valueOf(accentColor())
}
- private fun setColors(colorLight: Boolean, color: Int) {
- setLightStatusbar(colorLight)
- toolbar.setTitleTextColor(
- MaterialValueHelper.getPrimaryTextColor(
- this@ShareInstagramStory,
- colorLight
- )
- )
- toolbar.navigationIcon?.setTintList(
- ColorStateList.valueOf(
- MaterialValueHelper.getPrimaryTextColor(
- this@ShareInstagramStory,
- colorLight
- )
- )
- )
- mainContent.background =
+ private fun setColors(color: Int) {
+ binding.mainContent.background =
GradientDrawable(
GradientDrawable.Orientation.TOP_BOTTOM,
intArrayOf(color, Color.BLACK)
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/SupportDevelopmentActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/SupportDevelopmentActivity.kt
deleted file mode 100644
index 9dcec81b8..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/activities/SupportDevelopmentActivity.kt
+++ /dev/null
@@ -1,252 +0,0 @@
-package code.name.monkey.retromusic.activities
-
-import android.content.Intent
-import android.graphics.Paint
-import android.os.AsyncTask
-import android.os.Bundle
-import android.util.Log
-import android.view.LayoutInflater
-import android.view.MenuItem
-import android.view.View
-import android.view.ViewGroup
-import android.widget.TextView
-import android.widget.Toast
-import androidx.annotation.LayoutRes
-import androidx.appcompat.widget.AppCompatImageView
-import androidx.recyclerview.widget.DefaultItemAnimator
-import androidx.recyclerview.widget.GridLayoutManager
-import androidx.recyclerview.widget.RecyclerView
-import code.name.monkey.appthemehelper.ThemeStore
-import code.name.monkey.appthemehelper.util.ATHUtil
-import code.name.monkey.appthemehelper.util.TintHelper
-import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
-import code.name.monkey.retromusic.BuildConfig
-import code.name.monkey.retromusic.R
-import code.name.monkey.retromusic.activities.base.AbsBaseActivity
-import code.name.monkey.retromusic.extensions.textColorPrimary
-import code.name.monkey.retromusic.extensions.textColorSecondary
-import com.anjlab.android.iab.v3.BillingProcessor
-import com.anjlab.android.iab.v3.SkuDetails
-import com.anjlab.android.iab.v3.TransactionDetails
-import kotlinx.android.synthetic.main.activity_about.toolbar
-import kotlinx.android.synthetic.main.activity_donation.*
-import java.lang.ref.WeakReference
-import java.util.*
-
-class SupportDevelopmentActivity : AbsBaseActivity(), BillingProcessor.IBillingHandler {
-
- companion object {
- val TAG: String = SupportDevelopmentActivity::class.java.simpleName
- const val DONATION_PRODUCT_IDS = R.array.donation_ids
- private const val TEZ_REQUEST_CODE = 123
- }
-
- var billingProcessor: BillingProcessor? = null
- private var skuDetailsLoadAsyncTask: AsyncTask<*, *, *>? = null
-
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- if (item.itemId == android.R.id.home) {
- onBackPressed()
- return true
- }
- return super.onOptionsItemSelected(item)
- }
-
- fun donate(i: Int) {
- val ids = resources.getStringArray(DONATION_PRODUCT_IDS)
- billingProcessor?.purchase(this, ids[i])
- }
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_donation)
-
- setStatusbarColorAuto()
- setNavigationbarColorAuto()
- setTaskDescriptionColorAuto()
- setLightNavigationBar(true)
-
- setupToolbar()
-
- billingProcessor = BillingProcessor(this, BuildConfig.GOOGLE_PLAY_LICENSING_KEY, this)
- TintHelper.setTint(progress, ThemeStore.accentColor(this))
- donation.setTextColor(ThemeStore.accentColor(this))
- }
-
- private fun setupToolbar() {
- val toolbarColor = ATHUtil.resolveColor(this, R.attr.colorSurface)
- toolbar.setBackgroundColor(toolbarColor)
- ToolbarContentTintHelper.colorBackButton(toolbar)
- setSupportActionBar(toolbar)
- }
-
- override fun onBillingInitialized() {
- loadSkuDetails()
- }
-
- private fun loadSkuDetails() {
- if (skuDetailsLoadAsyncTask != null) {
- skuDetailsLoadAsyncTask!!.cancel(false)
- }
- skuDetailsLoadAsyncTask = SkuDetailsLoadAsyncTask(this).execute()
- }
-
- override fun onProductPurchased(productId: String, details: TransactionDetails?) {
- //loadSkuDetails();
- Toast.makeText(this, R.string.thank_you, Toast.LENGTH_SHORT).show()
- }
-
- override fun onBillingError(errorCode: Int, error: Throwable?) {
- Log.e(TAG, "Billing error: code = $errorCode", error)
- }
-
- override fun onPurchaseHistoryRestored() {
- //loadSkuDetails();
- Toast.makeText(this, R.string.restored_previous_purchases, Toast.LENGTH_SHORT).show()
- }
-
- override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
- if (!billingProcessor!!.handleActivityResult(requestCode, resultCode, data)) {
- super.onActivityResult(requestCode, resultCode, data)
- }
- if (requestCode == TEZ_REQUEST_CODE) {
- // Process based on the data in response.
- Log.d("result", data!!.getStringExtra("Status"))
- }
- }
-
- override fun onDestroy() {
- billingProcessor?.release()
- skuDetailsLoadAsyncTask?.cancel(true)
- super.onDestroy()
- }
-}
-
-private class SkuDetailsLoadAsyncTask internal constructor(supportDevelopmentActivity: SupportDevelopmentActivity) :
- AsyncTask>() {
-
- private val weakReference: WeakReference = WeakReference(
- supportDevelopmentActivity
- )
-
- override fun onPreExecute() {
- super.onPreExecute()
- val supportDevelopmentActivity = weakReference.get() ?: return
-
- supportDevelopmentActivity.progressContainer.visibility = View.VISIBLE
- supportDevelopmentActivity.recyclerView.visibility = View.GONE
- }
-
- override fun doInBackground(vararg params: Void): List? {
- val dialog = weakReference.get()
- if (dialog != null) {
- val ids =
- dialog.resources.getStringArray(SupportDevelopmentActivity.DONATION_PRODUCT_IDS)
- return dialog.billingProcessor!!.getPurchaseListingDetails(ArrayList(Arrays.asList(*ids)))
- }
- cancel(false)
- return null
- }
-
- override fun onPostExecute(skuDetails: List?) {
- super.onPostExecute(skuDetails)
- val dialog = weakReference.get() ?: return
-
- if (skuDetails == null || skuDetails.isEmpty()) {
- dialog.progressContainer.visibility = View.GONE
- return
- }
-
- dialog.progressContainer.visibility = View.GONE
- dialog.recyclerView.itemAnimator = DefaultItemAnimator()
- dialog.recyclerView.layoutManager = GridLayoutManager(dialog, 2)
- dialog.recyclerView.adapter = SkuDetailsAdapter(dialog, skuDetails)
- dialog.recyclerView.visibility = View.VISIBLE
- }
-}
-
-class SkuDetailsAdapter(
- private var donationsDialog: SupportDevelopmentActivity, objects: List
-) : RecyclerView.Adapter() {
-
- private var skuDetailsList: List = ArrayList()
-
- init {
- skuDetailsList = objects
- }
-
- private fun getIcon(position: Int): Int {
- return when (position) {
- 0 -> R.drawable.ic_cookie_white_24dp
- 1 -> R.drawable.ic_take_away_white_24dp
- 2 -> R.drawable.ic_take_away_coffe_white_24dp
- 3 -> R.drawable.ic_beer_white_24dp
- 4 -> R.drawable.ic_fast_food_meal_white_24dp
- 5 -> R.drawable.ic_popcorn_white_24dp
- 6 -> R.drawable.ic_card_giftcard_white_24dp
- 7 -> R.drawable.ic_food_croissant_white_24dp
- else -> R.drawable.ic_card_giftcard_white_24dp
- }
- }
-
- override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): ViewHolder {
- return ViewHolder(
- LayoutInflater.from(donationsDialog).inflate(
- LAYOUT_RES_ID,
- viewGroup,
- false
- )
- )
- }
-
- override fun onBindViewHolder(viewHolder: ViewHolder, i: Int) {
- val skuDetails = skuDetailsList[i]
- viewHolder.title.text = skuDetails.title.replace("(Retro Music Player \uD83C\uDFB5)", "")
- .trim { it <= ' ' }
- viewHolder.text.text = skuDetails.description
- viewHolder.text.visibility = View.GONE
- viewHolder.price.text = skuDetails.priceText
- viewHolder.image.setImageResource(getIcon(i))
-
- val purchased = donationsDialog.billingProcessor!!.isPurchased(skuDetails.productId)
- val titleTextColor = if (purchased) ATHUtil.resolveColor(
- donationsDialog,
- android.R.attr.textColorHint
- ) else donationsDialog.textColorPrimary()
- val contentTextColor =
- if (purchased) titleTextColor else donationsDialog.textColorSecondary()
-
- viewHolder.title.setTextColor(titleTextColor)
- viewHolder.text.setTextColor(contentTextColor)
- viewHolder.price.setTextColor(titleTextColor)
-
- strikeThrough(viewHolder.title, purchased)
- strikeThrough(viewHolder.text, purchased)
- strikeThrough(viewHolder.price, purchased)
-
- viewHolder.itemView.setOnTouchListener { _, _ -> purchased }
- viewHolder.itemView.setOnClickListener { donationsDialog.donate(i) }
- }
-
- override fun getItemCount(): Int {
- return skuDetailsList.size
- }
-
- class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
- var title: TextView = view.findViewById(R.id.itemTitle)
- var text: TextView = view.findViewById(R.id.itemText)
- var price: TextView = view.findViewById(R.id.itemPrice)
- var image: AppCompatImageView = view.findViewById(R.id.itemImage)
- }
-
- companion object {
- @LayoutRes
- private val LAYOUT_RES_ID = R.layout.item_donation_option
-
- private fun strikeThrough(textView: TextView, strikeThrough: Boolean) {
- textView.paintFlags =
- if (strikeThrough) textView.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
- else textView.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()
- }
- }
-}
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/UserInfoActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/UserInfoActivity.kt
deleted file mode 100644
index 5e1e8bbaa..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/activities/UserInfoActivity.kt
+++ /dev/null
@@ -1,218 +0,0 @@
-package code.name.monkey.retromusic.activities
-
-import android.app.Activity
-import android.content.Intent
-import android.content.res.ColorStateList
-import android.graphics.Bitmap
-import android.net.Uri
-import android.os.Bundle
-import android.text.TextUtils
-import android.view.MenuItem
-import android.widget.Toast
-import code.name.monkey.appthemehelper.util.ColorUtil
-import code.name.monkey.appthemehelper.util.MaterialUtil
-import code.name.monkey.appthemehelper.util.MaterialValueHelper
-import code.name.monkey.retromusic.Constants.USER_BANNER
-import code.name.monkey.retromusic.Constants.USER_PROFILE
-import code.name.monkey.retromusic.R
-import code.name.monkey.retromusic.activities.base.AbsBaseActivity
-import code.name.monkey.retromusic.extensions.accentColor
-import code.name.monkey.retromusic.extensions.applyToolbar
-import code.name.monkey.retromusic.glide.ProfileBannerGlideRequest
-import code.name.monkey.retromusic.glide.UserProfileGlideRequest
-import code.name.monkey.retromusic.util.ImageUtil
-import code.name.monkey.retromusic.util.PreferenceUtil
-import com.bumptech.glide.Glide
-import com.bumptech.glide.load.engine.DiskCacheStrategy
-import com.bumptech.glide.request.RequestListener
-import com.bumptech.glide.request.target.Target
-import com.github.dhaval2404.imagepicker.ImagePicker
-import com.github.dhaval2404.imagepicker.constant.ImageProvider
-import kotlinx.android.synthetic.main.activity_user_info.*
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-import java.io.BufferedOutputStream
-import java.io.File
-import java.io.FileOutputStream
-import java.io.IOException
-
-class UserInfoActivity : AbsBaseActivity() {
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_user_info)
- setStatusbarColorAuto()
- setNavigationbarColorAuto()
- setTaskDescriptionColorAuto()
- setLightNavigationBar(true)
- applyToolbar(toolbar)
-
- MaterialUtil.setTint(nameContainer, false)
- name.setText(PreferenceUtil.userName)
-
- userImage.setOnClickListener {
- pickNewPhoto()
- }
-
- bannerSelect.setOnClickListener {
- selectBannerImage()
- }
-
- next.setOnClickListener {
- val nameString = name.text.toString().trim { it <= ' ' }
- if (TextUtils.isEmpty(nameString)) {
- Toast.makeText(this, "Umm name is empty", Toast.LENGTH_SHORT).show()
- return@setOnClickListener
- }
- PreferenceUtil.userName = nameString
- setResult(Activity.RESULT_OK)
- finish()
- }
-
- val textColor =
- MaterialValueHelper.getPrimaryTextColor(this, ColorUtil.isColorLight(accentColor()))
- next.backgroundTintList = ColorStateList.valueOf(accentColor())
- next.iconTint = ColorStateList.valueOf(textColor)
- next.setTextColor(textColor)
- loadProfile()
- }
-
- private fun loadProfile() {
- bannerImage?.let {
- ProfileBannerGlideRequest.Builder.from(
- Glide.with(this),
- ProfileBannerGlideRequest.getBannerModel()
- ).build().into(it)
- }
- UserProfileGlideRequest.Builder.from(
- Glide.with(this),
- UserProfileGlideRequest.getUserModel()
- ).build().into(userImage)
- }
-
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- if (item.itemId == android.R.id.home) {
- onBackPressed()
- }
- return super.onOptionsItemSelected(item)
- }
-
- private fun selectBannerImage() {
- ImagePicker.with(this)
- .compress(1440)
- .provider(ImageProvider.GALLERY)
- .crop(16f, 9f)
- .start(PICK_BANNER_REQUEST)
- }
-
- private fun pickNewPhoto() {
- ImagePicker.with(this)
- .provider(ImageProvider.GALLERY)
- .cropSquare()
- .compress(1440)
- .start(PICK_IMAGE_REQUEST)
- }
-
-
- public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
- super.onActivityResult(requestCode, resultCode, data)
- if (resultCode == Activity.RESULT_OK && requestCode == PICK_IMAGE_REQUEST) {
- val fileUri = data?.data
- fileUri?.let { setAndSaveUserImage(it) }
- } else if (resultCode == Activity.RESULT_OK && requestCode == PICK_BANNER_REQUEST) {
- val fileUri = data?.data
- fileUri?.let { setAndSaveBannerImage(it) }
- } else if (resultCode == ImagePicker.RESULT_ERROR) {
- Toast.makeText(this, ImagePicker.getError(data), Toast.LENGTH_SHORT).show()
- } else {
- Toast.makeText(this, "Task Cancelled", Toast.LENGTH_SHORT).show()
- }
- }
-
- private fun setAndSaveBannerImage(fileUri: Uri) {
- Glide.with(this)
- .load(fileUri)
- .asBitmap()
- .diskCacheStrategy(DiskCacheStrategy.NONE)
- .listener(object : RequestListener {
- override fun onException(
- e: java.lang.Exception?,
- model: Any?,
- target: Target?,
- isFirstResource: Boolean
- ): Boolean {
- return false
- }
-
- override fun onResourceReady(
- resource: Bitmap?,
- model: Any?,
- target: Target?,
- isFromMemoryCache: Boolean,
- isFirstResource: Boolean
- ): Boolean {
- resource?.let { saveImage(it, USER_BANNER) }
- return false
- }
- })
- .into(bannerImage)
- }
-
- private fun saveImage(bitmap: Bitmap, fileName: String) {
- CoroutineScope(Dispatchers.IO).launch() {
- val appDir = applicationContext.filesDir
- val file = File(appDir, fileName)
- var successful = false
- try {
- val os = BufferedOutputStream(FileOutputStream(file))
- successful = ImageUtil.resizeBitmap(bitmap, 2048)
- .compress(Bitmap.CompressFormat.WEBP, 100, os)
- withContext(Dispatchers.IO) { os.close() }
- } catch (e: IOException) {
- e.printStackTrace()
- }
- if (successful) {
- withContext(Dispatchers.Main) {
- Toast.makeText(this@UserInfoActivity, "Updated", Toast.LENGTH_SHORT).show()
- }
- }
- }
- }
-
- private fun setAndSaveUserImage(fileUri: Uri) {
- Glide.with(this)
- .load(fileUri)
- .asBitmap()
- .diskCacheStrategy(DiskCacheStrategy.NONE)
- .listener(object : RequestListener {
- override fun onException(
- e: java.lang.Exception?,
- model: Any?,
- target: Target?,
- isFirstResource: Boolean
- ): Boolean {
- return false
- }
-
- override fun onResourceReady(
- resource: Bitmap?,
- model: Any?,
- target: Target?,
- isFromMemoryCache: Boolean,
- isFirstResource: Boolean
- ): Boolean {
- resource?.let { saveImage(it, USER_PROFILE) }
- return false
- }
- })
- .into(userImage)
- }
-
-
- companion object {
- private const val PICK_IMAGE_REQUEST = 9002
- private const val PICK_BANNER_REQUEST = 9004
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/WhatsNewActivity.java b/app/src/main/java/code/name/monkey/retromusic/activities/WhatsNewActivity.java
deleted file mode 100644
index 4f1a6ef3f..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/activities/WhatsNewActivity.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package code.name.monkey.retromusic.activities;
-
-
-import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.graphics.Color;
-import android.os.Bundle;
-import android.webkit.WebView;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.appcompat.widget.Toolbar;
-
-import java.io.BufferedReader;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.nio.charset.StandardCharsets;
-import java.util.Locale;
-
-import code.name.monkey.appthemehelper.ThemeStore;
-import code.name.monkey.appthemehelper.util.ATHUtil;
-import code.name.monkey.appthemehelper.util.ColorUtil;
-import code.name.monkey.appthemehelper.util.MaterialValueHelper;
-import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
-import code.name.monkey.retromusic.R;
-import code.name.monkey.retromusic.activities.base.AbsBaseActivity;
-import code.name.monkey.retromusic.util.PreferenceUtil;
-
-public class WhatsNewActivity extends AbsBaseActivity {
-
- private static String colorToCSS(int color) {
- return String.format(Locale.getDefault(), "rgba(%d, %d, %d, %d)", Color.red(color), Color.green(color),
- Color.blue(color), Color.alpha(color)); // on API 29, WebView doesn't load with hex colors
- }
-
- private static void setChangelogRead(@NonNull Context context) {
- try {
- PackageInfo pInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
- int currentVersion = pInfo.versionCode;
- PreferenceUtil.INSTANCE.setLastVersion(currentVersion);
- } catch (PackageManager.NameNotFoundException e) {
- e.printStackTrace();
- }
- }
-
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- setDrawUnderStatusBar();
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_whats_new);
- setStatusbarColorAuto();
- setNavigationbarColorAuto();
- setTaskDescriptionColorAuto();
-
- WebView webView = findViewById(R.id.webView);
- Toolbar toolbar = findViewById(R.id.toolbar);
- toolbar.setBackgroundColor(ATHUtil.INSTANCE.resolveColor(this, R.attr.colorSurface));
- toolbar.setNavigationOnClickListener(v -> onBackPressed());
- ToolbarContentTintHelper.colorBackButton(toolbar);
-
- try {
- StringBuilder buf = new StringBuilder();
- InputStream json = getAssets().open("retro-changelog.html");
- BufferedReader in = new BufferedReader(new InputStreamReader(json, StandardCharsets.UTF_8));
- String str;
- while ((str = in.readLine()) != null) {
- buf.append(str);
- }
- in.close();
-
- // Inject color values for WebView body background and links
- final boolean isDark = ATHUtil.INSTANCE.isWindowBackgroundDark(this);
- final int accentColor = ThemeStore.Companion.accentColor(this);
- final String backgroundColor = colorToCSS(ATHUtil.INSTANCE.resolveColor(this, R.attr.colorSurface, Color.parseColor(isDark ? "#424242" : "#ffffff")));
- final String contentColor = colorToCSS(Color.parseColor(isDark ? "#ffffff" : "#000000"));
- final String textColor = colorToCSS(Color.parseColor(isDark ? "#60FFFFFF" : "#80000000"));
- final String accentColorString = colorToCSS(ThemeStore.Companion.accentColor(this));
- final String accentTextColor = colorToCSS(MaterialValueHelper.getPrimaryTextColor(this, ColorUtil.INSTANCE.isColorLight(accentColor)));
- final String changeLog = buf.toString()
- .replace("{style-placeholder}", String.format("body { background-color: %s; color: %s; } li {color: %s;} .colorHeader {background-color: %s; color: %s;} .tag {color: %s;}", backgroundColor, contentColor, textColor, accentColorString, accentTextColor, accentColorString))
- .replace("{link-color}", colorToCSS(ThemeStore.Companion.accentColor(this)))
- .replace("{link-color-active}", colorToCSS(ColorUtil.INSTANCE.lightenColor(ThemeStore.Companion.accentColor(this))));
- webView.loadData(changeLog, "text/html", "UTF-8");
- } catch (Throwable e) {
- webView.loadData("Unable to load " + e.getLocalizedMessage() + "
", "text/html", "UTF-8");
- }
- setChangelogRead(this);
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/WhatsNewFragment.kt b/app/src/main/java/code/name/monkey/retromusic/activities/WhatsNewFragment.kt
new file mode 100644
index 000000000..48b39ed35
--- /dev/null
+++ b/app/src/main/java/code/name/monkey/retromusic/activities/WhatsNewFragment.kt
@@ -0,0 +1,153 @@
+package code.name.monkey.retromusic.activities
+
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.graphics.Color
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.webkit.WebResourceRequest
+import android.webkit.WebView
+import android.webkit.WebViewClient
+import androidx.core.content.pm.PackageInfoCompat
+import androidx.core.widget.NestedScrollView
+import androidx.fragment.app.FragmentActivity
+import code.name.monkey.appthemehelper.util.ATHUtil.isWindowBackgroundDark
+import code.name.monkey.appthemehelper.util.ColorUtil.isColorLight
+import code.name.monkey.appthemehelper.util.ColorUtil.lightenColor
+import code.name.monkey.appthemehelper.util.MaterialValueHelper.getPrimaryTextColor
+import code.name.monkey.retromusic.BuildConfig
+import code.name.monkey.retromusic.Constants
+import code.name.monkey.retromusic.databinding.FragmentWhatsNewBinding
+import code.name.monkey.retromusic.extensions.accentColor
+import code.name.monkey.retromusic.extensions.openUrl
+import code.name.monkey.retromusic.util.PreferenceUtil.lastVersion
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment
+import java.nio.charset.StandardCharsets
+import java.util.*
+
+class WhatsNewFragment : BottomSheetDialogFragment() {
+ private var _binding: FragmentWhatsNewBinding? = null
+ val binding get() = _binding!!
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ _binding = FragmentWhatsNewBinding.inflate(inflater, container, false)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ try {
+ val buf = StringBuilder()
+ val stream = requireContext().assets.open("retro-changelog.html")
+ stream.reader(StandardCharsets.UTF_8).buffered().use { br ->
+ var str: String?
+ while (br.readLine().also { str = it } != null) {
+ buf.append(str)
+ }
+ }
+
+ // Inject color values for WebView body background and links
+ val isDark = isWindowBackgroundDark(requireContext())
+ val accentColor = accentColor()
+ binding.webView.setBackgroundColor(0)
+ val contentColor = colorToCSS(Color.parseColor(if (isDark) "#ffffff" else "#000000"))
+ val textColor = colorToCSS(Color.parseColor(if (isDark) "#60FFFFFF" else "#80000000"))
+ val accentColorString = colorToCSS(accentColor())
+ val cardBackgroundColor =
+ colorToCSS(Color.parseColor(if (isDark) "#353535" else "#ffffff"))
+ val accentTextColor = colorToCSS(
+ getPrimaryTextColor(
+ requireContext(), isColorLight(accentColor)
+ )
+ )
+ val changeLog = buf.toString()
+ .replace(
+ "{style-placeholder}",
+ "body { color: $contentColor; } li {color: $textColor;} h3 {color: $accentColorString;} .tag {background-color: $accentColorString; color: $accentTextColor; } div{background-color: $cardBackgroundColor;}"
+ )
+ .replace("{link-color}", colorToCSS(accentColor()))
+ .replace(
+ "{link-color-active}",
+ colorToCSS(
+ lightenColor(accentColor())
+ )
+ )
+ binding.webView.loadData(changeLog, "text/html", "UTF-8")
+ binding.webView.webViewClient = object : WebViewClient() {
+ override fun shouldOverrideUrlLoading(
+ view: WebView?,
+ request: WebResourceRequest?
+ ): Boolean {
+ val url = request?.url ?: return false
+ //you can do checks here e.g. url.host equals to target one
+ startActivity(Intent(Intent.ACTION_VIEW, url))
+ return true
+ }
+ }
+ } catch (e: Throwable) {
+ binding.webView.loadData(
+ "Unable to load " + e.localizedMessage + "
", "text/html", "UTF-8"
+ )
+ }
+ setChangelogRead(requireContext())
+ binding.tgFab.setOnClickListener {
+ openUrl(Constants.TELEGRAM_CHANGE_LOG)
+ }
+ binding.tgFab.accentColor()
+ binding.tgFab.shrink()
+ binding.container.setOnScrollChangeListener { _: NestedScrollView?, _: Int, scrollY: Int, _: Int, oldScrollY: Int ->
+ val dy = scrollY - oldScrollY
+ if (dy > 0) {
+ binding.tgFab.shrink()
+ } else if (dy < 0) {
+ binding.tgFab.extend()
+ }
+ }
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ _binding = null
+ }
+
+ companion object {
+
+ const val TAG = "WhatsNewFragment"
+ private fun colorToCSS(color: Int): String {
+ return String.format(
+ Locale.getDefault(),
+ "rgba(%d, %d, %d, %d)",
+ Color.red(color),
+ Color.green(color),
+ Color.blue(color),
+ Color.alpha(color)
+ ) // on API 29, WebView doesn't load with hex colors
+ }
+
+ private fun setChangelogRead(context: Context) {
+ try {
+ val pInfo = context.packageManager.getPackageInfo(context.packageName, 0)
+ val currentVersion = PackageInfoCompat.getLongVersionCode(pInfo)
+ lastVersion = currentVersion
+ } catch (e: PackageManager.NameNotFoundException) {
+ e.printStackTrace()
+ }
+ }
+
+ fun showChangeLog(activity: FragmentActivity) {
+ val pInfo = activity.packageManager.getPackageInfo(activity.packageName, 0)
+ val currentVersion = PackageInfoCompat.getLongVersionCode(pInfo)
+ if (currentVersion > lastVersion && !BuildConfig.DEBUG) {
+ val changelogBottomSheet = WhatsNewFragment()
+ changelogBottomSheet.show(activity.supportFragmentManager, TAG)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/albums/AlbumDetailsActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/albums/AlbumDetailsActivity.kt
deleted file mode 100644
index 4095bb7ce..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/activities/albums/AlbumDetailsActivity.kt
+++ /dev/null
@@ -1,396 +0,0 @@
-package code.name.monkey.retromusic.activities.albums
-
-import android.app.ActivityOptions
-import android.content.Intent
-import android.os.Bundle
-import android.transition.Slide
-import android.view.Menu
-import android.view.MenuItem
-import android.view.SubMenu
-import android.view.View
-import android.widget.ImageView
-import androidx.core.app.ActivityCompat
-import androidx.lifecycle.ViewModelProvider
-import androidx.recyclerview.widget.DefaultItemAnimator
-import androidx.recyclerview.widget.GridLayoutManager
-import androidx.recyclerview.widget.LinearLayoutManager
-import code.name.monkey.appthemehelper.util.ATHUtil
-import code.name.monkey.appthemehelper.util.MaterialUtil
-import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
-import code.name.monkey.retromusic.R
-import code.name.monkey.retromusic.activities.base.AbsSlidingMusicPanelActivity
-import code.name.monkey.retromusic.activities.tageditor.AbsTagEditorActivity
-import code.name.monkey.retromusic.activities.tageditor.AlbumTagEditorActivity
-import code.name.monkey.retromusic.adapter.album.HorizontalAlbumAdapter
-import code.name.monkey.retromusic.adapter.song.SimpleSongAdapter
-import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog
-import code.name.monkey.retromusic.dialogs.DeleteSongsDialog
-import code.name.monkey.retromusic.extensions.extraNotNull
-import code.name.monkey.retromusic.extensions.ripAlpha
-import code.name.monkey.retromusic.extensions.show
-import code.name.monkey.retromusic.extensions.surfaceColor
-import code.name.monkey.retromusic.glide.AlbumGlideRequest
-import code.name.monkey.retromusic.glide.ArtistGlideRequest
-import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
-import code.name.monkey.retromusic.helper.MusicPlayerRemote
-import code.name.monkey.retromusic.helper.SortOrder.AlbumSongSortOrder
-import code.name.monkey.retromusic.interfaces.CabHolder
-import code.name.monkey.retromusic.model.Album
-import code.name.monkey.retromusic.model.Artist
-import code.name.monkey.retromusic.mvp.presenter.AlbumDetailsView
-import code.name.monkey.retromusic.rest.model.LastFmAlbum
-import code.name.monkey.retromusic.util.*
-import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
-import com.afollestad.materialcab.MaterialCab
-import com.bumptech.glide.Glide
-import kotlinx.android.synthetic.main.activity_album.*
-import kotlinx.android.synthetic.main.activity_album_content.*
-import java.util.*
-import android.util.Pair as UtilPair
-
-class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView, CabHolder {
- override fun openCab(menuRes: Int, callback: MaterialCab.Callback): MaterialCab {
- cab?.let {
- if (it.isActive) it.finish()
- }
- cab = MaterialCab(this, R.id.cab_stub)
- .setMenu(menuRes)
- .setCloseDrawableRes(R.drawable.ic_close_white_24dp)
- .setBackgroundColor(
- RetroColorUtil.shiftBackgroundColorForLightText(
- ATHUtil.resolveColor(
- this,
- R.attr.colorSurface
- )
- )
- )
- .start(callback)
- return cab as MaterialCab
- }
-
- private lateinit var viewModel: AlbumDetailsViewModel
- private lateinit var simpleSongAdapter: SimpleSongAdapter
- private lateinit var album: Album
- private lateinit var artistImage: ImageView
- private var cab: MaterialCab? = null
- private val savedSortOrder: String
- get() = PreferenceUtil.albumDetailSongSortOrder
-
- override fun createContentView(): View {
- return wrapSlidingMusicPanel(R.layout.activity_album)
- }
-
- private fun windowEnterTransition() {
- val slide = Slide()
- slide.excludeTarget(R.id.appBarLayout, true)
- slide.excludeTarget(R.id.status_bar, true)
- slide.excludeTarget(android.R.id.statusBarBackground, true)
- slide.excludeTarget(android.R.id.navigationBarBackground, true)
- window.enterTransition = slide
- }
-
- override fun onCreate(savedInstanceState: Bundle?) {
- setDrawUnderStatusBar()
- super.onCreate(savedInstanceState)
- setStatusbarColorAuto()
- setNavigationbarColorAuto()
- setTaskDescriptionColorAuto()
- setLightNavigationBar(true)
- setBottomBarVisibility(View.GONE)
- window.sharedElementsUseOverlay = true
- windowEnterTransition()
-
- val albumId = extraNotNull(EXTRA_ALBUM_ID).value
- ActivityCompat.postponeEnterTransition(this)
- val viewModelFactory = AlbumDetailsViewModelFactory(application, albumId)
- viewModel = ViewModelProvider(this, viewModelFactory).get(AlbumDetailsViewModel::class.java)
- viewModel.getAlbum().observe(this, androidx.lifecycle.Observer {
- ActivityCompat.startPostponedEnterTransition(this@AlbumDetailsActivity)
- album(it)
- })
- viewModel.getArtist().observe(this, androidx.lifecycle.Observer {
- loadArtistImage(it)
- })
- viewModel.getAlbumInfo().observe(this, androidx.lifecycle.Observer {
- aboutAlbum(it)
- })
- setupRecyclerView()
- artistImage = findViewById(R.id.artistImage)
- artistImage.setOnClickListener {
- val artistPairs = ActivityOptions.makeSceneTransitionAnimation(
- this,
- UtilPair.create(
- artistImage,
- getString(R.string.transition_artist_image)
- )
- )
- NavigationUtil.goToArtistOptions(this, album.artistId, artistPairs)
- }
- playAction.apply {
- setOnClickListener { MusicPlayerRemote.openQueue(album.songs!!, 0, true) }
- }
- shuffleAction.apply {
- setOnClickListener { MusicPlayerRemote.openAndShuffleQueue(album.songs!!, true) }
- }
-
- aboutAlbumText.setOnClickListener {
- if (aboutAlbumText.maxLines == 4) {
- aboutAlbumText.maxLines = Integer.MAX_VALUE
- } else {
- aboutAlbumText.maxLines = 4
- }
- }
- }
-
- private fun setupRecyclerView() {
- simpleSongAdapter = SimpleSongAdapter(this, ArrayList(), R.layout.item_song, this)
- recyclerView.apply {
- layoutManager = LinearLayoutManager(this@AlbumDetailsActivity)
- itemAnimator = DefaultItemAnimator()
- isNestedScrollingEnabled = false
- adapter = simpleSongAdapter
- }
- }
-
- override fun complete() {
- ActivityCompat.startPostponedEnterTransition(this)
- }
-
- override fun album(album: Album) {
- complete()
- if (album.songs!!.isEmpty()) {
- finish()
- return
- }
- this.album = album
-
- albumTitle.text = album.title
- val songText =
- resources.getQuantityString(
- R.plurals.albumSongs,
- album.songCount,
- album.songCount
- )
- songTitle.text = songText
-
- if (MusicUtil.getYearString(album.year) == "-") {
- albumText.text = String.format(
- "%s • %s",
- album.artistName,
- MusicUtil.getReadableDurationString(MusicUtil.getTotalDuration(album.songs))
- )
- } else {
- albumText.text = String.format(
- "%s • %s • %s",
- album.artistName,
- MusicUtil.getYearString(album.year),
- MusicUtil.getReadableDurationString(MusicUtil.getTotalDuration(album.songs))
- )
- }
- loadAlbumCover()
- simpleSongAdapter.swapDataSet(album.songs)
- viewModel.loadArtist(album.artistId)
- viewModel.loadAlbumInfo(album)
- }
-
- override fun moreAlbums(albums: List) {
- moreTitle.show()
- moreRecyclerView.show()
- moreTitle.text = String.format(getString(R.string.label_more_from), album.artistName)
-
- val albumAdapter = HorizontalAlbumAdapter(this, albums, null)
- moreRecyclerView.layoutManager = GridLayoutManager(
- this,
- 1,
- GridLayoutManager.HORIZONTAL,
- false
- )
- moreRecyclerView.adapter = albumAdapter
- }
-
- override fun aboutAlbum(lastFmAlbum: LastFmAlbum) {
- if (lastFmAlbum.album != null) {
- if (lastFmAlbum.album.wiki != null) {
- aboutAlbumText.show()
- aboutAlbumTitle.show()
- aboutAlbumTitle.text =
- String.format(getString(R.string.about_album_label), lastFmAlbum.album.name)
- aboutAlbumText.text = lastFmAlbum.album.wiki.content
- }
- if (lastFmAlbum.album.listeners.isNotEmpty()) {
- listeners.show()
- listenersLabel.show()
- scrobbles.show()
- scrobblesLabel.show()
-
- listeners.text = RetroUtil.formatValue(lastFmAlbum.album.listeners.toFloat())
- scrobbles.text = RetroUtil.formatValue(lastFmAlbum.album.playcount.toFloat())
- }
- }
- }
-
- override fun loadArtistImage(artist: Artist) {
- ArtistGlideRequest.Builder.from(Glide.with(this), artist)
- .generatePalette(this)
- .build()
- .dontAnimate()
- .dontTransform()
- .into(object : RetroMusicColoredTarget(artistImage) {
- override fun onColorReady(colors: MediaNotificationProcessor) {
- }
- })
- }
-
- private fun loadAlbumCover() {
- AlbumGlideRequest.Builder.from(Glide.with(this), album.safeGetFirstSong())
- .checkIgnoreMediaStore(this)
- .ignoreMediaStore(PreferenceUtil.isIgnoreMediaStoreArtwork)
- .generatePalette(this)
- .build()
- .dontAnimate()
- .dontTransform()
- .into(object : RetroMusicColoredTarget(image) {
- override fun onColorReady(colors: MediaNotificationProcessor) {
- setColors(colors)
- }
- })
- }
-
- private fun setColors(color: MediaNotificationProcessor) {
- val buttonColor = if (PreferenceUtil.isAdaptiveColor)
- color.backgroundColor.ripAlpha()
- else
- ATHUtil.resolveColor(this, R.attr.colorSurface)
-
- MaterialUtil.setTint(button = shuffleAction, color = buttonColor)
- MaterialUtil.setTint(button = playAction, color = buttonColor)
-
- toolbar.setBackgroundColor(surfaceColor())
- setSupportActionBar(toolbar)
- supportActionBar?.title = null
- }
-
- override fun onCreateOptionsMenu(menu: Menu): Boolean {
- menuInflater.inflate(R.menu.menu_album_detail, menu)
- val sortOrder = menu.findItem(R.id.action_sort_order)
- setUpSortOrderMenu(sortOrder.subMenu)
- ToolbarContentTintHelper.handleOnCreateOptionsMenu(
- this,
- toolbar,
- menu,
- getToolbarBackgroundColor(toolbar)
- )
- return super.onCreateOptionsMenu(menu)
- }
-
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- return handleSortOrderMenuItem(item)
- }
-
- private fun handleSortOrderMenuItem(item: MenuItem): Boolean {
- var sortOrder: String? = null
- val songs = simpleSongAdapter.dataSet
- when (item.itemId) {
- R.id.action_play_next -> {
- MusicPlayerRemote.playNext(songs)
- return true
- }
- R.id.action_add_to_current_playing -> {
- MusicPlayerRemote.enqueue(songs)
- return true
- }
- R.id.action_add_to_playlist -> {
- AddToPlaylistDialog.create(songs).show(supportFragmentManager, "ADD_PLAYLIST")
- return true
- }
- R.id.action_delete_from_device -> {
- DeleteSongsDialog.create(songs).show(supportFragmentManager, "DELETE_SONGS")
- return true
- }
- android.R.id.home -> {
- super.onBackPressed()
- return true
- }
- R.id.action_tag_editor -> {
- val intent = Intent(this, AlbumTagEditorActivity::class.java)
- intent.putExtra(AbsTagEditorActivity.EXTRA_ID, album.id)
- val options = ActivityOptions.makeSceneTransitionAnimation(
- this,
- albumCoverContainer,
- "${getString(R.string.transition_album_art)}_${album.id}"
- )
- startActivityForResult(
- intent,
- TAG_EDITOR_REQUEST, options.toBundle()
- )
- return true
- }
- /*Sort*/
- R.id.action_sort_order_title -> sortOrder = AlbumSongSortOrder.SONG_A_Z
- R.id.action_sort_order_title_desc -> sortOrder = AlbumSongSortOrder.SONG_Z_A
- R.id.action_sort_order_track_list -> sortOrder = AlbumSongSortOrder.SONG_TRACK_LIST
- R.id.action_sort_order_artist_song_duration ->
- sortOrder = AlbumSongSortOrder.SONG_DURATION
- }
- if (sortOrder != null) {
- item.isChecked = true
- setSaveSortOrder(sortOrder)
- }
- return true
- }
-
- private fun setUpSortOrderMenu(sortOrder: SubMenu) {
- when (savedSortOrder) {
- AlbumSongSortOrder.SONG_A_Z -> sortOrder.findItem(R.id.action_sort_order_title)
- .isChecked = true
- AlbumSongSortOrder.SONG_Z_A -> sortOrder.findItem(R.id.action_sort_order_title_desc)
- .isChecked = true
- AlbumSongSortOrder.SONG_TRACK_LIST -> sortOrder.findItem(R.id.action_sort_order_track_list)
- .isChecked = true
- AlbumSongSortOrder.SONG_DURATION -> sortOrder.findItem(R.id.action_sort_order_artist_song_duration)
- .isChecked = true
- }
- }
-
- private fun setSaveSortOrder(sortOrder: String) {
- PreferenceUtil.albumDetailSongSortOrder = sortOrder
- when (sortOrder) {
- AlbumSongSortOrder.SONG_TRACK_LIST -> album.songs?.sortWith(Comparator { o1, o2 ->
- o1.trackNumber.compareTo(
- o2.trackNumber
- )
- })
- AlbumSongSortOrder.SONG_A_Z -> album.songs?.sortWith(Comparator { o1, o2 ->
- o1.title.compareTo(
- o2.title
- )
- })
- AlbumSongSortOrder.SONG_Z_A -> album.songs?.sortWith(Comparator { o1, o2 ->
- o2.title.compareTo(
- o1.title
- )
- })
- AlbumSongSortOrder.SONG_DURATION -> album.songs?.sortWith(Comparator { o1, o2 ->
- o1.duration.compareTo(
- o2.duration
- )
- })
- }
- album.songs?.let { simpleSongAdapter.swapDataSet(it) }
- }
-
-
- override fun onBackPressed() {
- if (cab != null && cab!!.isActive) {
- cab?.finish()
- } else {
- super.onBackPressed()
- }
- }
-
- companion object {
-
- const val EXTRA_ALBUM_ID = "extra_album_id"
- private const val TAG_EDITOR_REQUEST = 2001
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/albums/AlbumDetailsViewModel.kt b/app/src/main/java/code/name/monkey/retromusic/activities/albums/AlbumDetailsViewModel.kt
deleted file mode 100644
index 29dd6c327..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/activities/albums/AlbumDetailsViewModel.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-package code.name.monkey.retromusic.activities.albums
-
-import android.app.Application
-import androidx.lifecycle.AndroidViewModel
-import androidx.lifecycle.LiveData
-import androidx.lifecycle.MutableLiveData
-import androidx.lifecycle.viewModelScope
-import code.name.monkey.retromusic.model.Album
-import code.name.monkey.retromusic.model.Artist
-import code.name.monkey.retromusic.providers.RepositoryImpl
-import code.name.monkey.retromusic.rest.model.LastFmAlbum
-import kotlinx.coroutines.Deferred
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.async
-import kotlinx.coroutines.launch
-
-class AlbumDetailsViewModel(
- application: Application,
- private val albumId: Int
-) : AndroidViewModel(application) {
- private val _repository = RepositoryImpl(application.applicationContext)
- private val _album = MutableLiveData()
- private val _artist = MutableLiveData()
- private val _lastFmAlbum = MutableLiveData()
-
- fun getAlbum(): LiveData = _album
- fun getArtist(): LiveData = _artist
- fun getAlbumInfo(): LiveData = _lastFmAlbum
-
- init {
- loadDetails()
- }
-
- private fun loadDetails() = viewModelScope.launch {
- val album = loadAlbumAsync.await() ?: throw NullPointerException("Album couldn't found")
- _album.postValue(album)
- }
-
- fun loadAlbumInfo(album: Album) = viewModelScope.launch(Dispatchers.IO) {
- val lastFmAlbum = _repository.albumInfo(album.artistName ?: "-", album.title ?: "-")
- _lastFmAlbum.postValue(lastFmAlbum)
- }
-
- fun loadArtist(artistId: Int) = viewModelScope.launch(Dispatchers.IO) {
- val artist = _repository.artistById(artistId)
- _artist.postValue(artist)
- }
-
- private val loadAlbumAsync: Deferred
- get() = viewModelScope.async(Dispatchers.IO) {
- _repository.albumById(albumId)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/albums/AlbumDetailsViewModelFactory.kt b/app/src/main/java/code/name/monkey/retromusic/activities/albums/AlbumDetailsViewModelFactory.kt
deleted file mode 100644
index 7f5aa8476..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/activities/albums/AlbumDetailsViewModelFactory.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-package code.name.monkey.retromusic.activities.albums
-
-import android.app.Application
-import androidx.lifecycle.ViewModel
-import androidx.lifecycle.ViewModelProvider
-
-class AlbumDetailsViewModelFactory(
- private val application: Application,
- private val albumId: Int
-) :
- ViewModelProvider.AndroidViewModelFactory(application) {
- override fun create(modelClass: Class): T {
- return if (modelClass.isAssignableFrom(AlbumDetailsViewModel::class.java)) {
- AlbumDetailsViewModel(application, albumId) as T
- } else {
- throw IllegalArgumentException("ViewModel Not Found")
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/artists/ArtistDetailActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/artists/ArtistDetailActivity.kt
deleted file mode 100755
index 7fb6ed1b5..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/activities/artists/ArtistDetailActivity.kt
+++ /dev/null
@@ -1,327 +0,0 @@
-package code.name.monkey.retromusic.activities.artists
-
-import android.app.Activity
-import android.content.Intent
-import android.os.Bundle
-import android.text.Spanned
-import android.transition.Slide
-import android.view.Menu
-import android.view.MenuItem
-import android.view.View
-import android.widget.Toast
-import androidx.core.app.ActivityCompat
-import androidx.core.text.HtmlCompat
-import androidx.lifecycle.ViewModelProvider
-import androidx.recyclerview.widget.DefaultItemAnimator
-import androidx.recyclerview.widget.GridLayoutManager
-import androidx.recyclerview.widget.LinearLayoutManager
-import code.name.monkey.appthemehelper.util.ATHUtil
-import code.name.monkey.appthemehelper.util.MaterialUtil
-import code.name.monkey.retromusic.R
-import code.name.monkey.retromusic.activities.base.AbsSlidingMusicPanelActivity
-import code.name.monkey.retromusic.adapter.album.HorizontalAlbumAdapter
-import code.name.monkey.retromusic.adapter.song.SimpleSongAdapter
-import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog
-import code.name.monkey.retromusic.extensions.extraNotNull
-import code.name.monkey.retromusic.extensions.ripAlpha
-import code.name.monkey.retromusic.extensions.show
-import code.name.monkey.retromusic.extensions.surfaceColor
-import code.name.monkey.retromusic.glide.ArtistGlideRequest
-import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
-import code.name.monkey.retromusic.helper.MusicPlayerRemote
-import code.name.monkey.retromusic.interfaces.CabHolder
-import code.name.monkey.retromusic.model.Artist
-import code.name.monkey.retromusic.mvp.presenter.ArtistDetailsView
-import code.name.monkey.retromusic.rest.model.LastFmArtist
-import code.name.monkey.retromusic.util.*
-import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
-import com.afollestad.materialcab.MaterialCab
-import com.bumptech.glide.Glide
-import kotlinx.android.synthetic.main.activity_artist_content.*
-import kotlinx.android.synthetic.main.activity_artist_details.*
-import java.util.*
-import kotlin.collections.ArrayList
-
-class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView, CabHolder {
- override fun openCab(menuRes: Int, callback: MaterialCab.Callback): MaterialCab {
- cab?.let {
- if (it.isActive) it.finish()
- }
- cab = MaterialCab(this, R.id.cab_stub)
- .setMenu(menuRes)
- .setCloseDrawableRes(R.drawable.ic_close_white_24dp)
- .setBackgroundColor(
- RetroColorUtil.shiftBackgroundColorForLightText(
- ATHUtil.resolveColor(
- this,
- R.attr.colorSurface
- )
- )
- )
- .start(callback)
- return cab as MaterialCab
- }
-
- private var cab: MaterialCab? = null
- private var biography: Spanned? = null
- private lateinit var artist: Artist
- private lateinit var songAdapter: SimpleSongAdapter
- private lateinit var albumAdapter: HorizontalAlbumAdapter
- private var forceDownload: Boolean = false
- private lateinit var viewModel: ArtistDetailsViewModel
-
- override fun createContentView(): View {
- return wrapSlidingMusicPanel(R.layout.activity_artist_details)
- }
-
- private fun windowEnterTransition() {
- val slide = Slide()
- slide.excludeTarget(R.id.appBarLayout, true)
- slide.excludeTarget(R.id.status_bar, true)
- slide.excludeTarget(android.R.id.statusBarBackground, true)
- slide.excludeTarget(android.R.id.navigationBarBackground, true)
- window.enterTransition = slide
- }
-
- override fun onCreate(savedInstanceState: Bundle?) {
- setDrawUnderStatusBar()
- super.onCreate(savedInstanceState)
- setStatusbarColorAuto()
- setNavigationbarColorAuto()
- setTaskDescriptionColorAuto()
- setLightNavigationBar(true)
- setBottomBarVisibility(View.GONE)
- window.sharedElementsUseOverlay = true
- windowEnterTransition()
-
- val artistId = extraNotNull(EXTRA_ARTIST_ID).value
- val viewModelFactory = ArtistDetailsViewModelFactory(application, artistId)
- viewModel =
- ViewModelProvider(this, viewModelFactory).get(ArtistDetailsViewModel::class.java)
- viewModel.getArtist().observe(this, androidx.lifecycle.Observer {
- ActivityCompat.startPostponedEnterTransition(this@ArtistDetailActivity)
- artist(it)
- })
- viewModel.getArtistInfo().observe(this, androidx.lifecycle.Observer {
- artistInfo(it)
- })
- ActivityCompat.postponeEnterTransition(this)
-
- setupRecyclerView()
-
- playAction.apply {
- setOnClickListener { MusicPlayerRemote.openQueue(artist.songs, 0, true) }
- }
- shuffleAction.apply {
- setOnClickListener { MusicPlayerRemote.openAndShuffleQueue(artist.songs, true) }
- }
-
- biographyText.setOnClickListener {
- if (biographyText.maxLines == 4) {
- biographyText.maxLines = Integer.MAX_VALUE
- } else {
- biographyText.maxLines = 4
- }
- }
- }
-
- private fun setupRecyclerView() {
- albumAdapter = HorizontalAlbumAdapter(this, ArrayList(), null)
- albumRecyclerView.apply {
- itemAnimator = DefaultItemAnimator()
- layoutManager = GridLayoutManager(this.context, 1, GridLayoutManager.HORIZONTAL, false)
- adapter = albumAdapter
- }
- songAdapter = SimpleSongAdapter(this, ArrayList(), R.layout.item_song, this)
- recyclerView.apply {
- itemAnimator = DefaultItemAnimator()
- layoutManager = LinearLayoutManager(this.context)
- adapter = songAdapter
- }
- }
-
- override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
- super.onActivityResult(requestCode, resultCode, data)
- when (requestCode) {
- REQUEST_CODE_SELECT_IMAGE -> if (resultCode == Activity.RESULT_OK) {
- data?.data?.let {
- CustomArtistImageUtil.getInstance(this).setCustomArtistImage(artist, it)
- }
- }
- else -> if (resultCode == Activity.RESULT_OK) {
- //reload()
- }
- }
- }
-
- override fun showEmptyView() {
- }
-
- override fun complete() {
- ActivityCompat.startPostponedEnterTransition(this)
- }
-
- override fun artist(artist: Artist) {
- complete()
- if (artist.songCount <= 0) {
- finish()
- }
- this.artist = artist
- loadArtistImage()
-
- if (RetroUtil.isAllowedToDownloadMetadata(this)) {
- loadBiography(artist.name)
- }
- artistTitle.text = artist.name
- text.text = String.format(
- "%s • %s",
- MusicUtil.getArtistInfoString(this, artist),
- MusicUtil.getReadableDurationString(MusicUtil.getTotalDuration(artist.songs))
- )
- val songText =
- resources.getQuantityString(
- R.plurals.albumSongs,
- artist.songCount,
- artist.songCount
- )
- val albumText =
- resources.getQuantityString(
- R.plurals.albums,
- artist.songCount,
- artist.songCount
- )
- songTitle.text = songText
- albumTitle.text = albumText
- songAdapter.swapDataSet(artist.songs)
- albumAdapter.swapDataSet(artist.albums!!)
- }
-
- private fun loadBiography(
- name: String,
- lang: String? = Locale.getDefault().language
- ) {
- biography = null
- this.lang = lang
- viewModel.loadBiography(name, lang, null)
- }
-
- override fun artistInfo(lastFmArtist: LastFmArtist?) {
- if (lastFmArtist != null && lastFmArtist.artist != null) {
- val bioContent = lastFmArtist.artist.bio.content
- if (bioContent != null && bioContent.trim { it <= ' ' }.isNotEmpty()) {
- biographyText.visibility = View.VISIBLE
- biographyTitle.visibility = View.VISIBLE
- biography = HtmlCompat.fromHtml(bioContent, HtmlCompat.FROM_HTML_MODE_LEGACY)
- biographyText.text = biography
- if (lastFmArtist.artist.stats.listeners.isNotEmpty()) {
- listeners.show()
- listenersLabel.show()
- scrobbles.show()
- scrobblesLabel.show()
-
- listeners.text =
- RetroUtil.formatValue(lastFmArtist.artist.stats.listeners.toFloat())
- scrobbles.text =
- RetroUtil.formatValue(lastFmArtist.artist.stats.playcount.toFloat())
- }
- }
- }
-
- // If the "lang" parameter is set and no biography is given, retry with default language
- if (biography == null && lang != null) {
- loadBiography(artist.name, null)
- }
- }
-
- private var lang: String? = null
-
- private fun loadArtistImage() {
- ArtistGlideRequest.Builder.from(Glide.with(this), artist).generatePalette(this).build()
- .dontAnimate().into(object : RetroMusicColoredTarget(image) {
- override fun onColorReady(colors: MediaNotificationProcessor) {
- setColors(colors)
- }
- })
- }
-
- private fun setColors(color: MediaNotificationProcessor) {
- val buttonColor = if (PreferenceUtil.isAdaptiveColor)
- color.backgroundColor.ripAlpha()
- else
- ATHUtil.resolveColor(this, R.attr.colorSurface)
-
- MaterialUtil.setTint(button = shuffleAction, color = buttonColor)
- MaterialUtil.setTint(button = playAction, color = buttonColor)
-
-
- toolbar.setBackgroundColor(surfaceColor())
- setSupportActionBar(toolbar)
- supportActionBar?.title = null
- }
-
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- return handleSortOrderMenuItem(item)
- }
-
- private fun handleSortOrderMenuItem(item: MenuItem): Boolean {
- val songs = artist.songs
- when (item.itemId) {
- android.R.id.home -> {
- super.onBackPressed()
- return true
- }
- R.id.action_play_next -> {
- MusicPlayerRemote.playNext(songs)
- return true
- }
- R.id.action_add_to_current_playing -> {
- MusicPlayerRemote.enqueue(songs)
- return true
- }
- R.id.action_add_to_playlist -> {
- AddToPlaylistDialog.create(songs).show(supportFragmentManager, "ADD_PLAYLIST")
- return true
- }
- R.id.action_set_artist_image -> {
- val intent = Intent(Intent.ACTION_GET_CONTENT)
- intent.type = "image/*"
- startActivityForResult(
- Intent.createChooser(intent, getString(R.string.pick_from_local_storage)),
- REQUEST_CODE_SELECT_IMAGE
- )
- return true
- }
- R.id.action_reset_artist_image -> {
- Toast.makeText(
- this@ArtistDetailActivity,
- resources.getString(R.string.updating),
- Toast.LENGTH_SHORT
- )
- .show()
- CustomArtistImageUtil.getInstance(this@ArtistDetailActivity)
- .resetCustomArtistImage(artist)
- forceDownload = true
- return true
- }
- }
- return true
- }
-
- override fun onCreateOptionsMenu(menu: Menu): Boolean {
- menuInflater.inflate(R.menu.menu_artist_detail, menu)
- return super.onCreateOptionsMenu(menu)
- }
-
- override fun onBackPressed() {
- if (cab != null && cab!!.isActive) {
- cab?.finish()
- } else {
- super.onBackPressed()
- }
- }
-
- companion object {
- const val EXTRA_ARTIST_ID = "extra_artist_id"
- const val REQUEST_CODE_SELECT_IMAGE = 9003
- }
-}
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/artists/ArtistDetailsViewModel.kt b/app/src/main/java/code/name/monkey/retromusic/activities/artists/ArtistDetailsViewModel.kt
deleted file mode 100644
index fc535b99f..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/activities/artists/ArtistDetailsViewModel.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-package code.name.monkey.retromusic.activities.artists
-
-import android.app.Application
-import androidx.lifecycle.AndroidViewModel
-import androidx.lifecycle.LiveData
-import androidx.lifecycle.MutableLiveData
-import androidx.lifecycle.viewModelScope
-import code.name.monkey.retromusic.model.Artist
-import code.name.monkey.retromusic.providers.RepositoryImpl
-import code.name.monkey.retromusic.rest.model.LastFmArtist
-import kotlinx.coroutines.Deferred
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.async
-import kotlinx.coroutines.launch
-
-class ArtistDetailsViewModel(
- application: Application,
- private val artistId: Int
-) : AndroidViewModel(application) {
-
- private val loadArtistDetailsAsync: Deferred
- get() = viewModelScope.async(Dispatchers.IO) {
- _repository.artistById(artistId)
- }
- private val _repository = RepositoryImpl(application.applicationContext)
- private val _artist = MutableLiveData()
- private val _lastFmArtist = MutableLiveData()
-
- fun getArtist(): LiveData = _artist
- fun getArtistInfo(): LiveData = _lastFmArtist
-
- init {
- loadArtistDetails()
- }
-
- private fun loadArtistDetails() = viewModelScope.launch {
- val artist =
- loadArtistDetailsAsync.await() ?: throw NullPointerException("Album couldn't found")
- _artist.postValue(artist)
- }
-
- fun loadBiography(name: String, lang: String?, cache: String?) = viewModelScope.launch {
- val info = _repository.artistInfo(name, lang, cache)
- _lastFmArtist.postValue(info)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/artists/ArtistDetailsViewModelFactory.kt b/app/src/main/java/code/name/monkey/retromusic/activities/artists/ArtistDetailsViewModelFactory.kt
deleted file mode 100644
index e3ab552bb..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/activities/artists/ArtistDetailsViewModelFactory.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-package code.name.monkey.retromusic.activities.artists
-
-import android.app.Application
-import androidx.lifecycle.ViewModel
-import androidx.lifecycle.ViewModelProvider
-
-class ArtistDetailsViewModelFactory(
- private val application: Application,
- private val artistId: Int
-) :
- ViewModelProvider.AndroidViewModelFactory(application) {
- override fun create(modelClass: Class): T {
- return if (modelClass.isAssignableFrom(ArtistDetailsViewModel::class.java)) {
- ArtistDetailsViewModel(application, artistId) as T
- } else {
- throw IllegalArgumentException("ViewModel Not Found")
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsBaseActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsBaseActivity.kt
index 1afa57b44..1e0c110d5 100644
--- a/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsBaseActivity.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsBaseActivity.kt
@@ -1,18 +1,39 @@
+/*
+ * Copyright (c) 2020 Hemanth Savarla.
+ *
+ * Licensed under the GNU General Public License v3
+ *
+ * This is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ */
package code.name.monkey.retromusic.activities.base
import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
+import android.graphics.Rect
import android.media.AudioManager
import android.net.Uri
-import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.view.KeyEvent
+import android.view.MotionEvent
import android.view.View
+import android.view.inputmethod.InputMethodManager
+import android.widget.EditText
import androidx.core.app.ActivityCompat
-import code.name.monkey.appthemehelper.ThemeStore
+import androidx.core.content.getSystemService
+import code.name.monkey.appthemehelper.util.VersionUtils
import code.name.monkey.retromusic.R
+import code.name.monkey.retromusic.extensions.accentColor
+import code.name.monkey.retromusic.extensions.rootView
+import code.name.monkey.retromusic.util.logD
import com.google.android.material.snackbar.Snackbar
abstract class AbsBaseActivity : AbsThemeActivity() {
@@ -33,7 +54,7 @@ abstract class AbsBaseActivity : AbsThemeActivity() {
}
private val snackBarContainer: View
- get() = window.decorView
+ get() = rootView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -43,19 +64,12 @@ abstract class AbsBaseActivity : AbsThemeActivity() {
permissionDeniedMessage = null
}
- override fun onPostCreate(savedInstanceState: Bundle?) {
- super.onPostCreate(savedInstanceState)
- if (!hasPermissions()) {
- requestPermissions()
- }
- }
-
override fun onResume() {
super.onResume()
val hasPermissions = hasPermissions()
if (hasPermissions != hadPermissions) {
hadPermissions = hasPermissions
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ if (VersionUtils.hasMarshmallow()) {
onHasPermissionsChanged(hasPermissions)
}
}
@@ -63,7 +77,7 @@ abstract class AbsBaseActivity : AbsThemeActivity() {
protected open fun onHasPermissionsChanged(hasPermissions: Boolean) {
// implemented by sub classes
- println(hasPermissions)
+ logD(hasPermissions)
}
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
@@ -78,17 +92,15 @@ abstract class AbsBaseActivity : AbsThemeActivity() {
}
protected open fun requestPermissions() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- requestPermissions(permissions, PERMISSION_REQUEST)
- }
+ ActivityCompat.requestPermissions(this, permissions, PERMISSION_REQUEST)
}
protected fun hasPermissions(): Boolean {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- for (permission in permissions) {
- if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
- return false
- }
+ for (permission in permissions) {
+ if (ActivityCompat.checkSelfPermission(this,
+ permission) != PackageManager.PERMISSION_GRANTED
+ ) {
+ return false
}
}
return true
@@ -97,51 +109,96 @@ abstract class AbsBaseActivity : AbsThemeActivity() {
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array,
- grantResults: IntArray
+ grantResults: IntArray,
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == PERMISSION_REQUEST) {
for (grantResult in grantResults) {
if (grantResult != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(
- this@AbsBaseActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE
+ this@AbsBaseActivity, Manifest.permission.READ_EXTERNAL_STORAGE,
+ ) || ActivityCompat.shouldShowRequestPermissionRationale(
+ this@AbsBaseActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE,
)
) {
- //User has deny from permission dialog
+ // User has deny from permission dialog
Snackbar.make(
snackBarContainer,
permissionDeniedMessage!!,
- Snackbar.LENGTH_INDEFINITE
+ Snackbar.LENGTH_SHORT
)
- .setAction(code.name.monkey.retromusic.R.string.action_grant) { requestPermissions() }
- .setActionTextColor(ThemeStore.accentColor(this)).show()
+ .setAction(R.string.action_grant) { requestPermissions() }
+ .setActionTextColor(accentColor()).show()
} else {
// User has deny permission and checked never show permission dialog so you can redirect to Application settings page
Snackbar.make(
snackBarContainer,
permissionDeniedMessage!!,
Snackbar.LENGTH_INDEFINITE
- ).setAction(code.name.monkey.retromusic.R.string.action_settings) {
- val intent = Intent()
- intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
- val uri = Uri.fromParts(
- "package",
- this@AbsBaseActivity.packageName,
- null
- )
- intent.data = uri
- startActivity(intent)
- }.setActionTextColor(ThemeStore.accentColor(this)).show()
+ )
+ .setAction(R.string.action_settings) {
+ val intent = Intent()
+ intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
+ val uri = Uri.fromParts(
+ "package",
+ this@AbsBaseActivity.packageName,
+ null
+ )
+ intent.data = uri
+ startActivity(intent)
+ }.setActionTextColor(accentColor()).show()
}
return
}
}
hadPermissions = true
onHasPermissionsChanged(true)
+ } else if (requestCode == BLUETOOTH_PERMISSION_REQUEST) {
+ for (grantResult in grantResults) {
+ if (grantResult != PackageManager.PERMISSION_GRANTED) {
+ if (ActivityCompat.shouldShowRequestPermissionRationale(
+ this@AbsBaseActivity, Manifest.permission.BLUETOOTH_CONNECT
+ )
+ ) {
+ // User has deny from permission dialog
+ Snackbar.make(
+ snackBarContainer,
+ R.string.permission_bluetooth_denied,
+ Snackbar.LENGTH_SHORT
+ )
+ .setAction(R.string.action_grant) {
+ ActivityCompat.requestPermissions(this,
+ arrayOf(Manifest.permission.BLUETOOTH_CONNECT),
+ BLUETOOTH_PERMISSION_REQUEST)
+ }
+ .setActionTextColor(accentColor()).show()
+ }
+ }
+ }
}
}
companion object {
const val PERMISSION_REQUEST = 100
+ const val BLUETOOTH_PERMISSION_REQUEST = 101
+ }
+
+ // this lets keyboard close when clicked in background
+ override fun dispatchTouchEvent(event: MotionEvent): Boolean {
+ if (event.action == MotionEvent.ACTION_DOWN) {
+ val v = currentFocus
+ if (v is EditText) {
+ val outRect = Rect()
+ v.getGlobalVisibleRect(outRect)
+ if (!outRect.contains(event.rawX.toInt(), event.rawY.toInt())) {
+ v.clearFocus()
+ getSystemService()?.hideSoftInputFromWindow(
+ v.windowToken,
+ 0
+ )
+ }
+ }
+ }
+ return super.dispatchTouchEvent(event)
}
}
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsMusicServiceActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsMusicServiceActivity.kt
index 9057625fd..f9f05c919 100644
--- a/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsMusicServiceActivity.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsMusicServiceActivity.kt
@@ -1,20 +1,49 @@
+/*
+ * Copyright (c) 2020 Hemanth Savarla.
+ *
+ * Licensed under the GNU General Public License v3
+ *
+ * This is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ */
package code.name.monkey.retromusic.activities.base
import android.Manifest
import android.content.*
import android.os.Bundle
import android.os.IBinder
+import androidx.core.content.ContextCompat
+import androidx.lifecycle.lifecycleScope
+import code.name.monkey.appthemehelper.util.VersionUtils
import code.name.monkey.retromusic.R
+import code.name.monkey.retromusic.db.toPlayCount
import code.name.monkey.retromusic.helper.MusicPlayerRemote
-import code.name.monkey.retromusic.interfaces.MusicServiceEventListener
-import code.name.monkey.retromusic.service.MusicService.*
+import code.name.monkey.retromusic.interfaces.IMusicServiceEventListener
+import code.name.monkey.retromusic.repository.RealRepository
+import code.name.monkey.retromusic.service.MusicService.Companion.FAVORITE_STATE_CHANGED
+import code.name.monkey.retromusic.service.MusicService.Companion.MEDIA_STORE_CHANGED
+import code.name.monkey.retromusic.service.MusicService.Companion.META_CHANGED
+import code.name.monkey.retromusic.service.MusicService.Companion.PLAY_STATE_CHANGED
+import code.name.monkey.retromusic.service.MusicService.Companion.QUEUE_CHANGED
+import code.name.monkey.retromusic.service.MusicService.Companion.REPEAT_MODE_CHANGED
+import code.name.monkey.retromusic.service.MusicService.Companion.SHUFFLE_MODE_CHANGED
+import code.name.monkey.retromusic.util.PreferenceUtil
+import code.name.monkey.retromusic.util.logD
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import org.koin.android.ext.android.inject
import java.lang.ref.WeakReference
-import java.util.*
-abstract class AbsMusicServiceActivity : AbsBaseActivity(), MusicServiceEventListener {
-
- private val mMusicServiceEventListeners = ArrayList()
+abstract class AbsMusicServiceActivity : AbsBaseActivity(), IMusicServiceEventListener {
+ private val mMusicServiceEventListeners = ArrayList()
+ private val repository: RealRepository by inject()
private var serviceToken: MusicPlayerRemote.ServiceToken? = null
private var musicStateReceiver: MusicStateReceiver? = null
private var receiverRegistered: Boolean = false
@@ -43,15 +72,15 @@ abstract class AbsMusicServiceActivity : AbsBaseActivity(), MusicServiceEventLis
}
}
- fun addMusicServiceEventListener(listener: MusicServiceEventListener?) {
- if (listener != null) {
- mMusicServiceEventListeners.add(listener)
+ fun addMusicServiceEventListener(listenerI: IMusicServiceEventListener?) {
+ if (listenerI != null) {
+ mMusicServiceEventListeners.add(listenerI)
}
}
- fun removeMusicServiceEventListener(listener: MusicServiceEventListener?) {
- if (listener != null) {
- mMusicServiceEventListeners.remove(listener)
+ fun removeMusicServiceEventListener(listenerI: IMusicServiceEventListener?) {
+ if (listenerI != null) {
+ mMusicServiceEventListeners.remove(listenerI)
}
}
@@ -68,8 +97,7 @@ abstract class AbsMusicServiceActivity : AbsBaseActivity(), MusicServiceEventLis
filter.addAction(MEDIA_STORE_CHANGED)
filter.addAction(FAVORITE_STATE_CHANGED)
- registerReceiver(musicStateReceiver, filter)
-
+ ContextCompat.registerReceiver(this, musicStateReceiver, filter, ContextCompat.RECEIVER_NOT_EXPORTED)
receiverRegistered = true
}
@@ -93,6 +121,16 @@ abstract class AbsMusicServiceActivity : AbsBaseActivity(), MusicServiceEventLis
for (listener in mMusicServiceEventListeners) {
listener.onPlayingMetaChanged()
}
+ lifecycleScope.launch(Dispatchers.IO) {
+ if (!PreferenceUtil.pauseHistory) {
+ repository.upsertSongInHistory(MusicPlayerRemote.currentSong)
+ }
+ val song = repository.findSongExistInPlayCount(MusicPlayerRemote.currentSong.id)
+ ?.apply { playCount += 1 }
+ ?: MusicPlayerRemote.currentSong.toPlayCount()
+
+ repository.upsertSongInPlayCount(song)
+ }
}
override fun onQueueChanged() {
@@ -125,6 +163,12 @@ abstract class AbsMusicServiceActivity : AbsBaseActivity(), MusicServiceEventLis
}
}
+ override fun onFavoriteStateChanged() {
+ for (listener in mMusicServiceEventListeners) {
+ listener.onFavoriteStateChanged()
+ }
+ }
+
override fun onHasPermissionsChanged(hasPermissions: Boolean) {
super.onHasPermissionsChanged(hasPermissions)
val intent = Intent(MEDIA_STORE_CHANGED)
@@ -133,15 +177,21 @@ abstract class AbsMusicServiceActivity : AbsBaseActivity(), MusicServiceEventLis
true
) // just in case we need to know this at some point
sendBroadcast(intent)
- println("sendBroadcast $hasPermissions")
+ logD("sendBroadcast $hasPermissions")
}
override fun getPermissionsToRequest(): Array {
- return arrayOf(
- Manifest.permission.READ_EXTERNAL_STORAGE,
- Manifest.permission.WRITE_EXTERNAL_STORAGE,
- Manifest.permission.BLUETOOTH
- )
+ return mutableListOf().apply {
+ if (VersionUtils.hasT()) {
+ add(Manifest.permission.READ_MEDIA_AUDIO)
+ add(Manifest.permission.POST_NOTIFICATIONS)
+ } else {
+ add(Manifest.permission.READ_EXTERNAL_STORAGE)
+ }
+ if (!VersionUtils.hasR()) {
+ add(Manifest.permission.WRITE_EXTERNAL_STORAGE)
+ }
+ }.toTypedArray()
}
private class MusicStateReceiver(activity: AbsMusicServiceActivity) : BroadcastReceiver() {
@@ -153,7 +203,8 @@ abstract class AbsMusicServiceActivity : AbsBaseActivity(), MusicServiceEventLis
val activity = reference.get()
if (activity != null && action != null) {
when (action) {
- FAVORITE_STATE_CHANGED, META_CHANGED -> activity.onPlayingMetaChanged()
+ FAVORITE_STATE_CHANGED -> activity.onFavoriteStateChanged()
+ META_CHANGED -> activity.onPlayingMetaChanged()
QUEUE_CHANGED -> activity.onQueueChanged()
PLAY_STATE_CHANGED -> activity.onPlayStateChanged()
REPEAT_MODE_CHANGED -> activity.onRepeatModeChanged()
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsSlidingMusicPanelActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsSlidingMusicPanelActivity.kt
index 411987f43..2a81ca9b4 100644
--- a/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsSlidingMusicPanelActivity.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsSlidingMusicPanelActivity.kt
@@ -1,24 +1,61 @@
+/*
+ * Copyright (c) 2020 Hemanth Savarla.
+ *
+ * Licensed under the GNU General Public License v3
+ *
+ * This is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ */
package code.name.monkey.retromusic.activities.base
+import android.animation.ArgbEvaluator
import android.animation.ValueAnimator
+import android.content.Intent
+import android.content.SharedPreferences
+import android.content.res.ColorStateList
import android.graphics.Color
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
+import android.view.animation.PathInterpolator
import android.widget.FrameLayout
-import androidx.annotation.LayoutRes
-import androidx.fragment.app.Fragment
-import code.name.monkey.appthemehelper.util.ATHUtil
-import code.name.monkey.appthemehelper.util.ColorUtil
+import androidx.activity.OnBackPressedCallback
+import androidx.core.animation.doOnEnd
+import androidx.core.view.*
+import androidx.fragment.app.commit
+import code.name.monkey.appthemehelper.util.VersionUtils
+import code.name.monkey.retromusic.ADAPTIVE_COLOR_APP
+import code.name.monkey.retromusic.ALBUM_COVER_STYLE
+import code.name.monkey.retromusic.ALBUM_COVER_TRANSFORM
+import code.name.monkey.retromusic.CAROUSEL_EFFECT
+import code.name.monkey.retromusic.CIRCLE_PLAY_BUTTON
+import code.name.monkey.retromusic.EXTRA_SONG_INFO
+import code.name.monkey.retromusic.KEEP_SCREEN_ON
+import code.name.monkey.retromusic.LIBRARY_CATEGORIES
+import code.name.monkey.retromusic.NOW_PLAYING_SCREEN_ID
import code.name.monkey.retromusic.R
-import code.name.monkey.retromusic.RetroBottomSheetBehavior
-import code.name.monkey.retromusic.extensions.hide
-import code.name.monkey.retromusic.extensions.show
-import code.name.monkey.retromusic.fragments.MiniPlayerFragment
+import code.name.monkey.retromusic.SCREEN_ON_LYRICS
+import code.name.monkey.retromusic.SWIPE_ANYWHERE_NOW_PLAYING
+import code.name.monkey.retromusic.SWIPE_DOWN_DISMISS
+import code.name.monkey.retromusic.TAB_TEXT_MODE
+import code.name.monkey.retromusic.TOGGLE_ADD_CONTROLS
+import code.name.monkey.retromusic.TOGGLE_FULL_SCREEN
+import code.name.monkey.retromusic.TOGGLE_VOLUME
+import code.name.monkey.retromusic.activities.PermissionActivity
+import code.name.monkey.retromusic.databinding.SlidingMusicPanelLayoutBinding
+import code.name.monkey.retromusic.extensions.*
+import code.name.monkey.retromusic.fragments.LibraryViewModel
import code.name.monkey.retromusic.fragments.NowPlayingScreen
import code.name.monkey.retromusic.fragments.NowPlayingScreen.*
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
+import code.name.monkey.retromusic.fragments.other.MiniPlayerFragment
import code.name.monkey.retromusic.fragments.player.adaptive.AdaptiveFragment
import code.name.monkey.retromusic.fragments.player.blur.BlurPlayerFragment
import code.name.monkey.retromusic.fragments.player.card.CardFragment
@@ -31,216 +68,488 @@ import code.name.monkey.retromusic.fragments.player.flat.FlatPlayerFragment
import code.name.monkey.retromusic.fragments.player.full.FullPlayerFragment
import code.name.monkey.retromusic.fragments.player.gradient.GradientPlayerFragment
import code.name.monkey.retromusic.fragments.player.material.MaterialFragment
+import code.name.monkey.retromusic.fragments.player.md3.MD3PlayerFragment
import code.name.monkey.retromusic.fragments.player.normal.PlayerFragment
-import code.name.monkey.retromusic.fragments.player.peak.PeakPlayerFragment
+import code.name.monkey.retromusic.fragments.player.peek.PeekPlayerFragment
import code.name.monkey.retromusic.fragments.player.plain.PlainPlayerFragment
import code.name.monkey.retromusic.fragments.player.simple.SimplePlayerFragment
import code.name.monkey.retromusic.fragments.player.tiny.TinyPlayerFragment
+import code.name.monkey.retromusic.fragments.queue.PlayingQueueFragment
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.model.CategoryInfo
-import code.name.monkey.retromusic.util.DensityUtil
import code.name.monkey.retromusic.util.PreferenceUtil
-import code.name.monkey.retromusic.views.BottomNavigationBarTinted
+import code.name.monkey.retromusic.util.ViewUtil
+import code.name.monkey.retromusic.util.logD
+import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.bottomsheet.BottomSheetBehavior
-import com.google.android.material.shape.MaterialShapeDrawable
-import com.google.android.material.shape.ShapeAppearanceModel
-import kotlinx.android.synthetic.main.sliding_music_panel_layout.*
+import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCallback
+import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_COLLAPSED
+import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_DRAGGING
+import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED
+import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_HIDDEN
+import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_SETTLING
+import com.google.android.material.bottomsheet.BottomSheetBehavior.from
+import org.koin.androidx.viewmodel.ext.android.viewModel
+
abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(),
- AbsPlayerFragment.Callbacks {
+ SharedPreferences.OnSharedPreferenceChangeListener {
companion object {
val TAG: String = AbsSlidingMusicPanelActivity::class.java.simpleName
}
- private lateinit var behavior: RetroBottomSheetBehavior
+ var fromNotification = false
+ private var windowInsets: WindowInsetsCompat? = null
+ protected val libraryViewModel by viewModel()
+ private lateinit var bottomSheetBehavior: BottomSheetBehavior
+ private lateinit var playerFragment: AbsPlayerFragment
private var miniPlayerFragment: MiniPlayerFragment? = null
- private var playerFragment: AbsPlayerFragment? = null
- private var cps: NowPlayingScreen? = null
- private var navigationBarColor: Int = 0
+ private var nowPlayingScreen: NowPlayingScreen? = null
private var taskColor: Int = 0
- private var lightStatusBar: Boolean = false
- private var lightNavigationBar: Boolean = false
- private var navigationBarColorAnimator: ValueAnimator? = null
- protected abstract fun createContentView(): View
- private lateinit var shapeDrawable: MaterialShapeDrawable
+ private var paletteColor: Int = Color.WHITE
+ private var navigationBarColor = 0
+
private val panelState: Int
- get() = behavior.state
+ get() = bottomSheetBehavior.state
+ private lateinit var binding: SlidingMusicPanelLayoutBinding
+ private var isInOneTabMode = false
- private val bottomSheetCallbackList = object : BottomSheetBehavior.BottomSheetCallback() {
+ private var navigationBarColorAnimator: ValueAnimator? = null
+ private val argbEvaluator: ArgbEvaluator = ArgbEvaluator()
- override fun onSlide(bottomSheet: View, slideOffset: Float) {
- setMiniPlayerAlphaProgress(slideOffset)
- dimBackground.show()
- dimBackground.alpha = slideOffset
- shapeDrawable.interpolation = 1 - slideOffset
+ private val onBackPressedCallback = object : OnBackPressedCallback(true) {
+ override fun handleOnBackPressed() {
+ println("Handle back press ${bottomSheetBehavior.state}")
+ if (!handleBackPress()) {
+ remove()
+ onBackPressedDispatcher.onBackPressed()
+ }
}
+ }
- override fun onStateChanged(bottomSheet: View, newState: Int) {
- when (newState) {
- BottomSheetBehavior.STATE_EXPANDED -> {
- onPanelExpanded()
- }
- BottomSheetBehavior.STATE_COLLAPSED -> {
- onPanelCollapsed()
- dimBackground.hide()
- }
- else -> {
+ private val bottomSheetCallbackList by lazy {
+ object : BottomSheetCallback() {
+ override fun onSlide(bottomSheet: View, slideOffset: Float) {
+ setMiniPlayerAlphaProgress(slideOffset)
+ navigationBarColorAnimator?.cancel()
+ setNavigationBarColorPreOreo(
+ argbEvaluator.evaluate(
+ slideOffset,
+ surfaceColor(),
+ navigationBarColor
+ ) as Int
+ )
+ }
+
+ override fun onStateChanged(bottomSheet: View, newState: Int) {
+ onBackPressedCallback.isEnabled = newState == STATE_EXPANDED
+ when (newState) {
+ STATE_EXPANDED -> {
+ onPanelExpanded()
+ if (PreferenceUtil.lyricsScreenOn && PreferenceUtil.showLyrics) {
+ keepScreenOn(true)
+ }
+ }
+
+ STATE_COLLAPSED -> {
+ onPanelCollapsed()
+ if ((PreferenceUtil.lyricsScreenOn && PreferenceUtil.showLyrics) || !PreferenceUtil.isScreenOnEnabled) {
+ keepScreenOn(false)
+ }
+ }
+
+ STATE_SETTLING, STATE_DRAGGING -> {
+ if (fromNotification) {
+ binding.navigationView.bringToFront()
+ fromNotification = false
+ }
+ }
+
+ STATE_HIDDEN -> {
+ MusicPlayerRemote.clearQueue()
+ }
+
+ else -> {
+ logD("Do a flip")
+ }
}
}
}
}
- fun getBottomSheetBehavior() = behavior
+ fun getBottomSheetBehavior() = bottomSheetBehavior
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- setContentView(createContentView())
+ if (!hasPermissions()) {
+ startActivity(Intent(this, PermissionActivity::class.java))
+ finish()
+ }
+ binding = SlidingMusicPanelLayoutBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+ binding.root.setOnApplyWindowInsetsListener { _, insets ->
+ windowInsets = WindowInsetsCompat.toWindowInsetsCompat(insets)
+ insets
+ }
chooseFragmentForTheme()
setupSlidingUpPanel()
+ setupBottomSheet()
+ updateColor()
+ if (!PreferenceUtil.materialYou) {
+ binding.slidingPanel.backgroundTintList = ColorStateList.valueOf(darkAccentColor())
+ navigationView.backgroundTintList = ColorStateList.valueOf(darkAccentColor())
+ }
+ navigationBarColor = surfaceColor()
+ onBackPressedDispatcher.addCallback(onBackPressedCallback)
+ }
- behavior = BottomSheetBehavior.from(slidingPanel) as RetroBottomSheetBehavior
-
- val themeColor = ATHUtil.resolveColor(this, android.R.attr.windowBackground, Color.GRAY)
- dimBackground.setBackgroundColor(ColorUtil.withAlpha(themeColor, 0.5f))
- shapeDrawable = MaterialShapeDrawable(
- ShapeAppearanceModel.builder(
- this,
- R.style.ClassicThemeOverLay,
- 0
- ).build()
- )
- slidingPanel.background = shapeDrawable
+ private fun setupBottomSheet() {
+ bottomSheetBehavior = from(binding.slidingPanel)
+ bottomSheetBehavior.addBottomSheetCallback(bottomSheetCallbackList)
+ bottomSheetBehavior.isHideable = PreferenceUtil.swipeDownToDismiss
+ bottomSheetBehavior.significantVelocityThreshold = 300
+ setMiniPlayerAlphaProgress(0F)
}
override fun onResume() {
super.onResume()
- if (cps != PreferenceUtil.nowPlayingScreen) {
+ PreferenceUtil.registerOnSharedPreferenceChangedListener(this)
+ if (nowPlayingScreen != PreferenceUtil.nowPlayingScreen) {
postRecreate()
}
- behavior.addBottomSheetCallback(bottomSheetCallbackList)
-
- if (behavior.state == BottomSheetBehavior.STATE_EXPANDED) {
+ if (bottomSheetBehavior.state == STATE_EXPANDED) {
setMiniPlayerAlphaProgress(1f)
}
}
override fun onDestroy() {
super.onDestroy()
- behavior.removeBottomSheetCallback(bottomSheetCallbackList)
- if (navigationBarColorAnimator != null) navigationBarColorAnimator?.cancel() // just in case
+ bottomSheetBehavior.removeBottomSheetCallback(bottomSheetCallbackList)
+ PreferenceUtil.unregisterOnSharedPreferenceChangedListener(this)
}
- protected fun wrapSlidingMusicPanel(@LayoutRes resId: Int): View {
- val slidingMusicPanelLayout =
- layoutInflater.inflate(R.layout.sliding_music_panel_layout, null)
- val contentContainer =
- slidingMusicPanelLayout.findViewById(R.id.mainContentFrame)
- layoutInflater.inflate(resId, contentContainer)
- return slidingMusicPanelLayout
+ override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
+ when (key) {
+ SWIPE_DOWN_DISMISS -> {
+ bottomSheetBehavior.isHideable = PreferenceUtil.swipeDownToDismiss
+ }
+
+ TOGGLE_ADD_CONTROLS -> {
+ miniPlayerFragment?.setUpButtons()
+ }
+
+ NOW_PLAYING_SCREEN_ID -> {
+ chooseFragmentForTheme()
+ binding.slidingPanel.updateLayoutParams {
+ height = if (nowPlayingScreen != Peek) {
+ ViewGroup.LayoutParams.MATCH_PARENT
+ } else {
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ }
+ onServiceConnected()
+ }
+ }
+
+ ALBUM_COVER_TRANSFORM, CAROUSEL_EFFECT,
+ ALBUM_COVER_STYLE, TOGGLE_VOLUME, EXTRA_SONG_INFO, CIRCLE_PLAY_BUTTON,
+ -> {
+ chooseFragmentForTheme()
+ onServiceConnected()
+ }
+
+ SWIPE_ANYWHERE_NOW_PLAYING -> {
+ playerFragment.addSwipeDetector()
+ }
+
+ ADAPTIVE_COLOR_APP -> {
+ if (PreferenceUtil.nowPlayingScreen in listOf(Normal, Material, Flat)) {
+ chooseFragmentForTheme()
+ onServiceConnected()
+ }
+ }
+
+ LIBRARY_CATEGORIES -> {
+ updateTabs()
+ }
+
+ TAB_TEXT_MODE -> {
+ navigationView.labelVisibilityMode = PreferenceUtil.tabTitleMode
+ }
+
+ TOGGLE_FULL_SCREEN -> {
+ recreate()
+ }
+
+ SCREEN_ON_LYRICS -> {
+ keepScreenOn(bottomSheetBehavior.state == STATE_EXPANDED && PreferenceUtil.lyricsScreenOn && PreferenceUtil.showLyrics || PreferenceUtil.isScreenOnEnabled)
+ }
+
+ KEEP_SCREEN_ON -> {
+ maybeSetScreenOn()
+ }
+ }
}
- private fun collapsePanel() {
- behavior.state = BottomSheetBehavior.STATE_COLLAPSED
+ fun collapsePanel() {
+ bottomSheetBehavior.state = STATE_COLLAPSED
}
fun expandPanel() {
- behavior.state = BottomSheetBehavior.STATE_EXPANDED
- setMiniPlayerAlphaProgress(1f)
+ bottomSheetBehavior.state = STATE_EXPANDED
}
private fun setMiniPlayerAlphaProgress(progress: Float) {
- if (miniPlayerFragment?.view == null) return
+ if (progress < 0) return
val alpha = 1 - progress
- miniPlayerFragment?.view?.alpha = alpha
- // necessary to make the views below clickable
- miniPlayerFragment?.view?.visibility = if (alpha == 0f) View.GONE else View.VISIBLE
+ miniPlayerFragment?.view?.alpha = 1 - (progress / 0.2F)
+ miniPlayerFragment?.view?.isGone = alpha == 0f
+ if (!isLandscape) {
+ binding.navigationView.translationY = progress * 500
+ binding.navigationView.alpha = alpha
+ }
+ binding.playerFragmentContainer.alpha = (progress - 0.2F) / 0.2F
+ }
- bottomNavigationView.translationY = progress * 500
- //bottomNavigationView.alpha = alpha
+ private fun animateNavigationBarColor(color: Int) {
+ if (VersionUtils.hasOreo()) return
+ navigationBarColorAnimator?.cancel()
+ navigationBarColorAnimator = ValueAnimator
+ .ofArgb(window.navigationBarColor, color).apply {
+ duration = ViewUtil.RETRO_MUSIC_ANIM_TIME.toLong()
+ interpolator = PathInterpolator(0.4f, 0f, 1f, 1f)
+ addUpdateListener { animation: ValueAnimator ->
+ setNavigationBarColorPreOreo(
+ animation.animatedValue as Int
+ )
+ }
+ start()
+ }
}
open fun onPanelCollapsed() {
+ setMiniPlayerAlphaProgress(0F)
// restore values
- super.setLightStatusbar(lightStatusBar)
- super.setTaskDescriptionColor(taskColor)
- super.setNavigationbarColor(navigationBarColor)
- super.setLightNavigationBar(lightNavigationBar)
-
-
- playerFragment?.setMenuVisibility(false)
- playerFragment?.userVisibleHint = false
- playerFragment?.onHide()
+ animateNavigationBarColor(surfaceColor())
+ setLightStatusBarAuto()
+ setLightNavigationBarAuto()
+ setTaskDescriptionColor(taskColor)
+ //playerFragment?.onHide()
}
open fun onPanelExpanded() {
- val playerFragmentColor = playerFragment!!.paletteColor
- super.setTaskDescriptionColor(playerFragmentColor)
-
- playerFragment?.setMenuVisibility(true)
- playerFragment?.userVisibleHint = true
- playerFragment?.onShow()
+ setMiniPlayerAlphaProgress(1F)
onPaletteColorChanged()
+ //playerFragment?.onShow()
}
private fun setupSlidingUpPanel() {
- slidingPanel.viewTreeObserver.addOnGlobalLayoutListener(object :
+ binding.slidingPanel.viewTreeObserver.addOnGlobalLayoutListener(object :
ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
- slidingPanel.viewTreeObserver.removeOnGlobalLayoutListener(this)
- if (cps != Peak) {
- val params = slidingPanel.layoutParams as ViewGroup.LayoutParams
- params.height = ViewGroup.LayoutParams.MATCH_PARENT
- slidingPanel.layoutParams = params
+ binding.slidingPanel.viewTreeObserver.removeOnGlobalLayoutListener(this)
+ if (nowPlayingScreen != Peek) {
+ binding.slidingPanel.updateLayoutParams {
+ height = ViewGroup.LayoutParams.MATCH_PARENT
+ }
}
when (panelState) {
- BottomSheetBehavior.STATE_EXPANDED -> onPanelExpanded()
- BottomSheetBehavior.STATE_COLLAPSED -> onPanelCollapsed()
- else -> playerFragment!!.onHide()
+ STATE_EXPANDED -> onPanelExpanded()
+ STATE_COLLAPSED -> onPanelCollapsed()
+ else -> {
+ // playerFragment!!.onHide()
+ }
}
}
})
}
- fun getBottomNavigationView(): BottomNavigationBarTinted {
- return bottomNavigationView
+ val navigationView get() = binding.navigationView
+
+ val slidingPanel get() = binding.slidingPanel
+
+ val isBottomNavVisible get() = navigationView.isVisible && navigationView is BottomNavigationView
+
+ override fun onServiceConnected() {
+ super.onServiceConnected()
+ hideBottomSheet(false)
}
- fun setBottomBarVisibility(visible: Int) {
- bottomNavigationView.visibility = visible
- hideBottomBar(MusicPlayerRemote.playingQueue.isEmpty())
+ override fun onQueueChanged() {
+ super.onQueueChanged()
+ // Mini player should be hidden in Playing Queue
+ // it may pop up if hideBottomSheet is called
+ if (currentFragment(R.id.fragment_container) !is PlayingQueueFragment) {
+ hideBottomSheet(MusicPlayerRemote.playingQueue.isEmpty())
+ }
}
- private fun hideBottomBar(hide: Boolean) {
- val heightOfBar = resources.getDimensionPixelSize(R.dimen.mini_player_height)
- val heightOfBarWithTabs =
- resources.getDimensionPixelSize(R.dimen.mini_player_height_expanded)
-
- if (hide) {
- behavior.isHideable = true
- behavior.peekHeight = 0
- bottomNavigationView.elevation = DensityUtil.dip2px(this, 10f).toFloat()
+ private fun handleBackPress(): Boolean {
+ if (panelState == STATE_EXPANDED) {
collapsePanel()
- } else {
- if (MusicPlayerRemote.playingQueue.isNotEmpty()) {
- slidingPanel.elevation = DensityUtil.dip2px(this, 10f).toFloat()
- bottomNavigationView.elevation = DensityUtil.dip2px(this, 10f).toFloat()
- behavior.isHideable = false
- behavior.peekHeight =
- if (bottomNavigationView.visibility == View.VISIBLE) {
- heightOfBarWithTabs
- } else {
- heightOfBar
- }
+ return true
+ }
+ return false
+ }
+
+ private fun onPaletteColorChanged() {
+ if (panelState == STATE_EXPANDED) {
+ navigationBarColor = surfaceColor()
+ setTaskDescColor(paletteColor)
+ val isColorLight = paletteColor.isColorLight
+ if (PreferenceUtil.isAdaptiveColor && (nowPlayingScreen == Normal || nowPlayingScreen == Flat || nowPlayingScreen == Material)) {
+ setLightNavigationBar(true)
+ setLightStatusBar(isColorLight)
+ } else if (nowPlayingScreen == Card || nowPlayingScreen == Blur || nowPlayingScreen == BlurCard) {
+ animateNavigationBarColor(Color.BLACK)
+ navigationBarColor = Color.BLACK
+ setLightStatusBar(false)
+ setLightNavigationBar(true)
+ } else if (nowPlayingScreen == Color || nowPlayingScreen == Tiny || nowPlayingScreen == Gradient) {
+ animateNavigationBarColor(paletteColor)
+ navigationBarColor = paletteColor
+ setLightNavigationBar(isColorLight)
+ setLightStatusBar(isColorLight)
+ } else if (nowPlayingScreen == Full) {
+ animateNavigationBarColor(paletteColor)
+ navigationBarColor = paletteColor
+ setLightNavigationBar(isColorLight)
+ setLightStatusBar(false)
+ } else if (nowPlayingScreen == Classic) {
+ setLightStatusBar(false)
+ } else if (nowPlayingScreen == Fit) {
+ setLightStatusBar(false)
}
}
}
+ private fun setTaskDescColor(color: Int) {
+ taskColor = color
+ if (panelState == STATE_COLLAPSED) {
+ setTaskDescriptionColor(color)
+ }
+ }
+
+ fun updateTabs() {
+ binding.navigationView.menu.clear()
+ val currentTabs: List = PreferenceUtil.libraryCategory
+ for (tab in currentTabs) {
+ if (tab.visible) {
+ val menu = tab.category
+ binding.navigationView.menu.add(0, menu.id, 0, menu.stringRes)
+ .setIcon(menu.icon)
+ }
+ }
+ if (binding.navigationView.menu.size() == 1) {
+ isInOneTabMode = true
+ binding.navigationView.isVisible = false
+ } else {
+ isInOneTabMode = false
+ }
+ }
+
+ private fun updateColor() {
+ libraryViewModel.paletteColor.observe(this) { color ->
+ this.paletteColor = color
+ onPaletteColorChanged()
+ }
+ }
+
+ fun setBottomNavVisibility(
+ visible: Boolean,
+ animate: Boolean = false,
+ hideBottomSheet: Boolean = MusicPlayerRemote.playingQueue.isEmpty(),
+ ) {
+ if (!ViewCompat.isLaidOut(navigationView)) {
+ return
+ }
+ if (isInOneTabMode) {
+ hideBottomSheet(
+ hide = hideBottomSheet,
+ animate = animate,
+ isBottomNavVisible = false
+ )
+ return
+ }
+ if (visible xor navigationView.isVisible) {
+ val mAnimate = animate && bottomSheetBehavior.state == STATE_COLLAPSED
+ if (mAnimate) {
+ if (visible) {
+ binding.navigationView.bringToFront()
+ binding.navigationView.show()
+ } else {
+ binding.navigationView.hide()
+ }
+ } else {
+ binding.navigationView.isVisible = visible
+ if (visible && bottomSheetBehavior.state != STATE_EXPANDED) {
+ binding.navigationView.bringToFront()
+ }
+ }
+ }
+ hideBottomSheet(
+ hide = hideBottomSheet,
+ animate = animate,
+ isBottomNavVisible = visible && navigationView is BottomNavigationView
+ )
+ }
+
+ fun hideBottomSheet(
+ hide: Boolean,
+ animate: Boolean = false,
+ isBottomNavVisible: Boolean = navigationView.isVisible && navigationView is BottomNavigationView,
+ ) {
+ val heightOfBar = windowInsets.getBottomInsets() + dip(R.dimen.mini_player_height)
+ val heightOfBarWithTabs = heightOfBar + dip(R.dimen.bottom_nav_height)
+ if (hide) {
+ bottomSheetBehavior.peekHeight = -windowInsets.getBottomInsets()
+ bottomSheetBehavior.state = STATE_COLLAPSED
+ libraryViewModel.setFabMargin(
+ this,
+ if (isBottomNavVisible) dip(R.dimen.bottom_nav_height) else 0
+ )
+ } else {
+ if (MusicPlayerRemote.playingQueue.isNotEmpty()) {
+ binding.slidingPanel.elevation = 0F
+ binding.navigationView.elevation = 5F
+ if (isBottomNavVisible) {
+ logD("List")
+ if (animate) {
+ bottomSheetBehavior.peekHeightAnimate(heightOfBarWithTabs)
+ } else {
+ bottomSheetBehavior.peekHeight = heightOfBarWithTabs
+ }
+ libraryViewModel.setFabMargin(
+ this,
+ dip(R.dimen.bottom_nav_mini_player_height)
+ )
+ } else {
+ logD("Details")
+ if (animate) {
+ bottomSheetBehavior.peekHeightAnimate(heightOfBar).doOnEnd {
+ binding.slidingPanel.bringToFront()
+ }
+ } else {
+ bottomSheetBehavior.peekHeight = heightOfBar
+ binding.slidingPanel.bringToFront()
+ }
+ libraryViewModel.setFabMargin(this, dip(R.dimen.mini_player_height))
+ }
+ }
+ }
+ }
+
+ fun setAllowDragging(allowDragging: Boolean) {
+ bottomSheetBehavior.isDraggable = allowDragging
+ hideBottomSheet(false)
+ }
+
private fun chooseFragmentForTheme() {
- cps = PreferenceUtil.nowPlayingScreen
- val fragment: Fragment = when (cps) {
+ nowPlayingScreen = PreferenceUtil.nowPlayingScreen
+
+ val fragment: AbsPlayerFragment = when (nowPlayingScreen) {
Blur -> BlurPlayerFragment()
Adaptive -> AdaptiveFragment()
Normal -> PlayerFragment()
@@ -253,136 +562,20 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(),
Simple -> SimplePlayerFragment()
Material -> MaterialFragment()
Color -> ColorFragment()
+ Gradient -> GradientPlayerFragment()
Tiny -> TinyPlayerFragment()
- Peak -> PeakPlayerFragment()
+ Peek -> PeekPlayerFragment()
Circle -> CirclePlayerFragment()
Classic -> ClassicPlayerFragment()
- Gradient -> GradientPlayerFragment()
+ MD3 -> MD3PlayerFragment()
else -> PlayerFragment()
- } // must implement AbsPlayerFragment
- supportFragmentManager.beginTransaction()
- .replace(R.id.playerFragmentContainer, fragment)
- .commit()
+ } // must extend AbsPlayerFragment
+ supportFragmentManager.commit {
+ replace(R.id.playerFragmentContainer, fragment)
+ }
supportFragmentManager.executePendingTransactions()
-
- playerFragment =
- supportFragmentManager.findFragmentById(R.id.playerFragmentContainer) as AbsPlayerFragment
- miniPlayerFragment =
- supportFragmentManager.findFragmentById(R.id.miniPlayerFragment) as MiniPlayerFragment
+ playerFragment = whichFragment(R.id.playerFragmentContainer)
+ miniPlayerFragment = whichFragment(R.id.miniPlayerFragment)
miniPlayerFragment?.view?.setOnClickListener { expandPanel() }
}
-
- override fun onServiceConnected() {
- super.onServiceConnected()
- if (MusicPlayerRemote.playingQueue.isNotEmpty()) {
- slidingPanel.viewTreeObserver.addOnGlobalLayoutListener(object :
- ViewTreeObserver.OnGlobalLayoutListener {
- override fun onGlobalLayout() {
- slidingPanel.viewTreeObserver.removeOnGlobalLayoutListener(this)
- hideBottomBar(false)
- }
- })
- } // don't call hideBottomBar(true) here as it causes a bug with the SlidingUpPanelLayout
- }
-
- override fun onQueueChanged() {
- super.onQueueChanged()
- hideBottomBar(MusicPlayerRemote.playingQueue.isEmpty())
- }
-
- override fun onBackPressed() {
- if (!handleBackPress()) super.onBackPressed()
- }
-
- open fun handleBackPress(): Boolean {
- if (behavior.peekHeight != 0 && playerFragment!!.onBackPressed()) return true
- if (panelState == BottomSheetBehavior.STATE_EXPANDED) {
- collapsePanel()
- return true
- }
- return false
- }
-
- override fun onPaletteColorChanged() {
- if (panelState == BottomSheetBehavior.STATE_EXPANDED) {
- val paletteColor = playerFragment!!.paletteColor
- super.setTaskDescriptionColor(paletteColor)
-
- val isColorLight = ColorUtil.isColorLight(paletteColor)
-
- if (PreferenceUtil.isAdaptiveColor && (cps == Normal || cps == Flat)) {
- super.setLightNavigationBar(true)
- super.setLightStatusbar(isColorLight)
- } else if (cps == Card || cps == Blur || cps == BlurCard) {
- super.setLightStatusbar(false)
- super.setLightNavigationBar(true)
- super.setNavigationbarColor(Color.BLACK)
- } else if (cps == Color || cps == Tiny || cps == Gradient) {
- super.setNavigationbarColor(paletteColor)
- super.setLightNavigationBar(isColorLight)
- super.setLightStatusbar(isColorLight)
- } else if (cps == Full) {
- super.setNavigationbarColor(paletteColor)
- super.setLightNavigationBar(isColorLight)
- super.setLightStatusbar(false)
- } else if (cps == Classic) {
- super.setLightStatusbar(false)
- } else if (cps == Fit) {
- super.setLightStatusbar(false)
- } else {
- super.setLightStatusbar(
- ColorUtil.isColorLight(
- ATHUtil.resolveColor(
- this,
- android.R.attr.windowBackground
- )
- )
- )
- super.setLightNavigationBar(true)
- }
- }
- }
-
- override fun setLightStatusbar(enabled: Boolean) {
- lightStatusBar = enabled
- if (panelState == BottomSheetBehavior.STATE_COLLAPSED) {
- super.setLightStatusbar(enabled)
- }
- }
-
- override fun setLightNavigationBar(enabled: Boolean) {
- lightNavigationBar = enabled
- if (panelState == BottomSheetBehavior.STATE_COLLAPSED) {
- super.setLightNavigationBar(enabled)
- }
- }
-
- override fun setNavigationbarColor(color: Int) {
- navigationBarColor = color
- if (panelState == BottomSheetBehavior.STATE_COLLAPSED) {
- if (navigationBarColorAnimator != null) navigationBarColorAnimator!!.cancel()
- super.setNavigationbarColor(color)
- }
- }
-
- override fun setTaskDescriptionColor(color: Int) {
- taskColor = color
- if (panelState == BottomSheetBehavior.STATE_COLLAPSED) {
- super.setTaskDescriptionColor(color)
- }
- }
-
- fun updateTabs() {
- bottomNavigationView.menu.clear()
- val currentTabs: List = PreferenceUtil.libraryCategory
- for (tab in currentTabs) {
- if (tab.visible) {
- val menu = tab.category
- bottomNavigationView.menu.add(0, menu.id, 0, menu.stringRes).setIcon(menu.icon)
- }
- }
- if (bottomNavigationView.menu.size() == 1) {
- bottomNavigationView.hide()
- }
- }
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsThemeActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsThemeActivity.kt
index 6746329b5..32b025f01 100644
--- a/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsThemeActivity.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsThemeActivity.kt
@@ -1,53 +1,69 @@
+/*
+ * Copyright (c) 2020 Hemanth Savarla.
+ *
+ * Licensed under the GNU General Public License v3
+ *
+ * This is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ */
package code.name.monkey.retromusic.activities.base
import android.content.Context
-import android.graphics.Color
import android.os.Bundle
import android.os.Handler
+import android.os.Looper
import android.view.KeyEvent
-import android.view.View
-import android.view.WindowManager
-import androidx.annotation.ColorInt
+import androidx.appcompat.app.AppCompatDelegate
import androidx.appcompat.app.AppCompatDelegate.setDefaultNightMode
-import code.name.monkey.appthemehelper.ATH
-import code.name.monkey.appthemehelper.ThemeStore
+import androidx.core.os.LocaleListCompat
import code.name.monkey.appthemehelper.common.ATHToolbarActivity
-import code.name.monkey.appthemehelper.util.ATHUtil
-import code.name.monkey.appthemehelper.util.ColorUtil
-import code.name.monkey.appthemehelper.util.MaterialDialogsUtil
import code.name.monkey.appthemehelper.util.VersionUtils
-import code.name.monkey.retromusic.LanguageContextWrapper
import code.name.monkey.retromusic.R
+import code.name.monkey.retromusic.extensions.*
import code.name.monkey.retromusic.util.PreferenceUtil
-import code.name.monkey.retromusic.util.RetroUtil
-import code.name.monkey.retromusic.util.theme.ThemeManager
-import java.util.*
+import code.name.monkey.retromusic.util.theme.getNightMode
+import code.name.monkey.retromusic.util.theme.getThemeResValue
abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable {
- private val handler = Handler()
+ private val handler = Handler(Looper.getMainLooper())
override fun onCreate(savedInstanceState: Bundle?) {
+ updateLocale()
updateTheme()
hideStatusBar()
super.onCreate(savedInstanceState)
- setImmersiveFullscreen()
- registerSystemUiVisibility()
- toggleScreenOn()
- MaterialDialogsUtil.updateMaterialDialogsThemeSingleton(this)
+ setEdgeToEdgeOrImmersive()
+ maybeSetScreenOn()
+ setLightNavigationBarAuto()
+ setLightStatusBarAuto(surfaceColor())
+ if (VersionUtils.hasQ()) {
+ window.decorView.isForceDarkAllowed = false
+ }
}
-
private fun updateTheme() {
- setTheme(ThemeManager.getThemeResValue(this))
- setDefaultNightMode(ThemeManager.getNightMode(this))
+ setTheme(getThemeResValue())
+ if (PreferenceUtil.materialYou) {
+ setDefaultNightMode(getNightMode())
+ }
+
+ if (PreferenceUtil.isCustomFont) {
+ setTheme(R.style.FontThemeOverlay)
+ }
}
- private fun toggleScreenOn() {
- if (PreferenceUtil.isScreenOnEnabled) {
- window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
- } else {
- window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
+ private fun updateLocale() {
+ val localeCode = PreferenceUtil.languageCode
+ if (PreferenceUtil.isLocaleAutoStorageEnabled) {
+ AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags(localeCode))
+ PreferenceUtil.isLocaleAutoStorageEnabled = true
}
}
@@ -62,119 +78,6 @@ abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable {
}
}
- fun hideStatusBar() {
- hideStatusBar(PreferenceUtil.isFullScreenMode)
- }
-
- private fun hideStatusBar(fullscreen: Boolean) {
- val statusBar = window.decorView.rootView.findViewById(R.id.status_bar)
- if (statusBar != null) {
- statusBar.visibility = if (fullscreen) View.GONE else View.VISIBLE
- }
- }
-
- fun setDrawUnderStatusBar() {
- RetroUtil.setAllowDrawUnderStatusBar(window)
- }
-
- fun setDrawUnderNavigationBar() {
- RetroUtil.setAllowDrawUnderNavigationBar(window)
- }
-
- /**
- * This will set the color of the view with the id "status_bar" on KitKat and Lollipop. On
- * Lollipop if no such view is found it will set the statusbar color using the native method.
- *
- * @param color the new statusbar color (will be shifted down on Lollipop and above)
- */
- fun setStatusbarColor(color: Int) {
- val statusBar = window.decorView.rootView.findViewById(R.id.status_bar)
- if (statusBar != null) {
- when {
- VersionUtils.hasMarshmallow() -> statusBar.setBackgroundColor(color)
- VersionUtils.hasLollipop() -> statusBar.setBackgroundColor(
- ColorUtil.darkenColor(
- color
- )
- )
- else -> statusBar.setBackgroundColor(color)
- }
- } else {
- when {
- VersionUtils.hasMarshmallow() -> window.statusBarColor = color
- else -> window.statusBarColor = ColorUtil.darkenColor(color)
- }
- }
- setLightStatusbarAuto(ATHUtil.resolveColor(this, R.attr.colorSurface))
- }
-
- fun setStatusbarColorAuto() {
- // we don't want to use statusbar color because we are doing the color darkening on our own to support KitKat
- setStatusbarColor(ATHUtil.resolveColor(this, R.attr.colorSurface))
- setLightStatusbarAuto(ATHUtil.resolveColor(this, R.attr.colorSurface))
- }
-
- open fun setTaskDescriptionColor(@ColorInt color: Int) {
- ATH.setTaskDescriptionColor(this, color)
- }
-
- fun setTaskDescriptionColorAuto() {
- setTaskDescriptionColor(ATHUtil.resolveColor(this, R.attr.colorSurface))
- }
-
- open fun setNavigationbarColor(color: Int) {
- if (ThemeStore.coloredNavigationBar(this)) {
- ATH.setNavigationbarColor(this, color)
- } else {
- ATH.setNavigationbarColor(this, Color.BLACK)
- }
- }
-
- fun setNavigationbarColorAuto() {
- setNavigationbarColor(ATHUtil.resolveColor(this, R.attr.colorSurface))
- }
-
- open fun setLightStatusbar(enabled: Boolean) {
- ATH.setLightStatusbar(this, enabled)
- }
-
- fun setLightStatusbarAuto(bgColor: Int) {
- setLightStatusbar(ColorUtil.isColorLight(bgColor))
- }
-
- open fun setLightNavigationBar(enabled: Boolean) {
- if (!ATHUtil.isWindowBackgroundDark(this) and ThemeStore.coloredNavigationBar(this)) {
- ATH.setLightNavigationbar(this, enabled)
- }
- }
-
- private fun registerSystemUiVisibility() {
- val decorView = window.decorView
- decorView.setOnSystemUiVisibilityChangeListener { visibility ->
- if (visibility and View.SYSTEM_UI_FLAG_FULLSCREEN == 0) {
- setImmersiveFullscreen()
- }
- }
- }
-
- private fun unregisterSystemUiVisibility() {
- val decorView = window.decorView
- decorView.setOnSystemUiVisibilityChangeListener(null)
- }
-
- private fun setImmersiveFullscreen() {
- val flags =
- (View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
-
- if (PreferenceUtil.isFullScreenMode) {
- window.decorView.systemUiVisibility = flags
- }
- }
-
- private fun exitFullscreen() {
- window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE
- }
-
override fun run() {
setImmersiveFullscreen()
}
@@ -186,7 +89,6 @@ abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable {
public override fun onDestroy() {
super.onDestroy()
- unregisterSystemUiVisibility()
exitFullscreen()
}
@@ -199,9 +101,6 @@ abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable {
}
override fun attachBaseContext(newBase: Context?) {
- val code = PreferenceUtil.languageCode
- if (code != "auto") {
- super.attachBaseContext(LanguageContextWrapper.wrap(newBase, Locale(code)))
- } else super.attachBaseContext(newBase)
+ super.attachBaseContext(newBase)
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/BugReportActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/BugReportActivity.kt
index 9e1bd13c0..e99881953 100644
--- a/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/BugReportActivity.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/BugReportActivity.kt
@@ -1,329 +1,91 @@
+/*
+ * Copyright (c) 2020 Hemanth Savarla.
+ *
+ * Licensed under the GNU General Public License v3
+ *
+ * This is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ */
package code.name.monkey.retromusic.activities.bugreport
-import android.app.Activity
-import android.app.Dialog
import android.content.ClipData
import android.content.ClipboardManager
-import android.content.Context
import android.content.Intent
-import android.net.Uri
import android.os.Bundle
-import android.text.TextUtils
import android.view.MenuItem
-import android.view.inputmethod.EditorInfo
-import android.widget.Toast
-import androidx.annotation.StringDef
-import androidx.annotation.StringRes
-import androidx.appcompat.app.AlertDialog
-import code.name.monkey.appthemehelper.ThemeStore
-import code.name.monkey.appthemehelper.util.ATHUtil
-import code.name.monkey.appthemehelper.util.MaterialUtil
+import androidx.core.content.getSystemService
+import androidx.core.net.toUri
import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.activities.base.AbsThemeActivity
import code.name.monkey.retromusic.activities.bugreport.model.DeviceInfo
-import code.name.monkey.retromusic.activities.bugreport.model.Report
-import code.name.monkey.retromusic.activities.bugreport.model.github.ExtraInfo
-import code.name.monkey.retromusic.activities.bugreport.model.github.GithubLogin
-import code.name.monkey.retromusic.activities.bugreport.model.github.GithubTarget
-import code.name.monkey.retromusic.misc.DialogAsyncTask
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import com.google.android.material.floatingactionbutton.FloatingActionButton
-import com.google.android.material.textfield.TextInputLayout
-import kotlinx.android.synthetic.main.activity_bug_report.*
-import kotlinx.android.synthetic.main.bug_report_card_device_info.*
-import kotlinx.android.synthetic.main.bug_report_card_report.*
-import org.eclipse.egit.github.core.Issue
-import org.eclipse.egit.github.core.client.GitHubClient
-import org.eclipse.egit.github.core.client.RequestException
-import org.eclipse.egit.github.core.service.IssueService
-import java.io.IOException
-
-private const val RESULT_SUCCESS = "RESULT_OK"
-private const val RESULT_BAD_CREDENTIALS = "RESULT_BAD_CREDENTIALS"
-private const val RESULT_INVALID_TOKEN = "RESULT_INVALID_TOKEN"
-private const val RESULT_ISSUES_NOT_ENABLED = "RESULT_ISSUES_NOT_ENABLED"
-private const val RESULT_UNKNOWN = "RESULT_UNKNOWN"
-
-@StringDef(
- RESULT_SUCCESS,
- RESULT_BAD_CREDENTIALS,
- RESULT_INVALID_TOKEN,
- RESULT_ISSUES_NOT_ENABLED,
- RESULT_UNKNOWN
-)
-@Retention(AnnotationRetention.SOURCE)
-private annotation class Result
+import code.name.monkey.retromusic.databinding.ActivityBugReportBinding
+import code.name.monkey.retromusic.extensions.accentColor
+import code.name.monkey.retromusic.extensions.setTaskDescriptionColorAuto
+import code.name.monkey.retromusic.extensions.showToast
open class BugReportActivity : AbsThemeActivity() {
+ private lateinit var binding: ActivityBugReportBinding
private var deviceInfo: DeviceInfo? = null
override fun onCreate(savedInstanceState: Bundle?) {
- setDrawUnderStatusBar()
super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_bug_report)
- setStatusbarColorAuto()
- setNavigationbarColorAuto()
+ binding = ActivityBugReportBinding.inflate(layoutInflater)
+ setContentView(binding.root)
setTaskDescriptionColorAuto()
initViews()
- if (TextUtils.isEmpty(title)) setTitle(R.string.report_an_issue)
+ if (title.isNullOrEmpty()) setTitle(R.string.report_an_issue)
deviceInfo = DeviceInfo(this)
- airTextDeviceInfo.text = deviceInfo.toString()
+ binding.cardDeviceInfo.airTextDeviceInfo.text = deviceInfo.toString()
}
private fun initViews() {
- val accentColor = ThemeStore.accentColor(this)
- val primaryColor = ATHUtil.resolveColor(this, R.attr.colorSurface)
- toolbar.setBackgroundColor(primaryColor)
- setSupportActionBar(toolbar)
- ToolbarContentTintHelper.colorBackButton(toolbar)
+ val accentColor = accentColor()
+ setSupportActionBar(binding.toolbar)
+ ToolbarContentTintHelper.colorBackButton(binding.toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
- TintHelper.setTintAuto(optionUseAccount, accentColor, false)
- optionUseAccount?.setOnClickListener {
- inputTitle.isEnabled = true
- inputDescription.isEnabled = true
- inputUsername.isEnabled = true
- inputPassword.isEnabled = true
- optionAnonymous.isChecked = false
- sendFab.hide(object : FloatingActionButton.OnVisibilityChangedListener() {
- override fun onHidden(fab: FloatingActionButton?) {
- super.onHidden(fab)
- sendFab.setImageResource(R.drawable.ic_send_white_24dp)
- sendFab.show()
- }
- })
- }
- TintHelper.setTintAuto(optionAnonymous, accentColor, false)
- optionAnonymous.setOnClickListener {
- inputTitle.isEnabled = false
- inputDescription.isEnabled = false
- inputUsername.isEnabled = false
- inputPassword.isEnabled = false
+ binding.cardDeviceInfo.airTextDeviceInfo.setOnClickListener { copyDeviceInfoToClipBoard() }
- optionUseAccount.isChecked = false
- sendFab.hide(object : FloatingActionButton.OnVisibilityChangedListener() {
- override fun onHidden(fab: FloatingActionButton?) {
- super.onHidden(fab)
- sendFab.setImageResource(R.drawable.ic_open_in_browser_white_24dp)
- sendFab.show()
- }
- })
- }
-
- inputPassword.setOnEditorActionListener { _, actionId, _ ->
- if (actionId == EditorInfo.IME_ACTION_SEND) {
- reportIssue()
- return@setOnEditorActionListener true
- }
- false
- }
-
- airTextDeviceInfo.setOnClickListener { copyDeviceInfoToClipBoard() }
-
- TintHelper.setTintAuto(sendFab, accentColor, true)
- sendFab.setOnClickListener { reportIssue() }
-
- MaterialUtil.setTint(inputLayoutTitle, false)
- MaterialUtil.setTint(inputLayoutDescription, false)
- MaterialUtil.setTint(inputLayoutUsername, false)
- MaterialUtil.setTint(inputLayoutPassword, false)
+ TintHelper.setTintAuto(binding.sendFab, accentColor, true)
+ binding.sendFab.setOnClickListener { reportIssue() }
}
private fun reportIssue() {
- if (optionUseAccount.isChecked) {
- if (!validateInput()) return
- val username = inputUsername.text.toString()
- val password = inputPassword.text.toString()
- sendBugReport(GithubLogin(username, password))
- } else {
- copyDeviceInfoToClipBoard()
-
- val i = Intent(Intent.ACTION_VIEW)
- i.data = Uri.parse(ISSUE_TRACKER_LINK)
- i.flags = Intent.FLAG_ACTIVITY_NEW_TASK
- startActivity(i)
- }
+ copyDeviceInfoToClipBoard()
+ val i = Intent(Intent.ACTION_VIEW)
+ i.data = ISSUE_TRACKER_LINK.toUri()
+ i.flags = Intent.FLAG_ACTIVITY_NEW_TASK
+ startActivity(i)
}
private fun copyDeviceInfoToClipBoard() {
- val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
+ val clipboard = getSystemService()
val clip = ClipData.newPlainText(getString(R.string.device_info), deviceInfo?.toMarkdown())
- clipboard.setPrimaryClip(clip)
- Toast.makeText(
- this@BugReportActivity,
- R.string.copied_device_info_to_clipboard,
- Toast.LENGTH_LONG
- ).show()
+ clipboard?.setPrimaryClip(clip)
+ showToast(R.string.copied_device_info_to_clipboard)
}
- private fun validateInput(): Boolean {
- var hasErrors = false
-
- if (optionUseAccount.isChecked) {
- if (TextUtils.isEmpty(inputUsername.text)) {
- setError(inputLayoutUsername, R.string.bug_report_no_username)
- hasErrors = true
- } else {
- removeError(inputLayoutUsername)
- }
-
- if (TextUtils.isEmpty(inputPassword.text)) {
- setError(inputLayoutPassword, R.string.bug_report_no_password)
- hasErrors = true
- } else {
- removeError(inputLayoutPassword)
- }
- }
-
- if (TextUtils.isEmpty(inputTitle.text)) {
- setError(inputLayoutTitle, R.string.bug_report_no_title)
- hasErrors = true
- } else {
- removeError(inputLayoutTitle)
- }
-
- if (TextUtils.isEmpty(inputDescription.text)) {
- setError(inputLayoutDescription, R.string.bug_report_no_description)
- hasErrors = true
- } else {
- removeError(inputLayoutDescription)
- }
-
- return !hasErrors
- }
-
- private fun setError(editTextLayout: TextInputLayout, @StringRes errorRes: Int) {
- editTextLayout.error = getString(errorRes)
- }
-
- private fun removeError(editTextLayout: TextInputLayout) {
- editTextLayout.error = null
- }
-
- private fun sendBugReport(login: GithubLogin) {
- if (!validateInput()) return
-
- val bugTitle = inputTitle.text.toString()
- val bugDescription = inputDescription.text.toString()
-
- val extraInfo = ExtraInfo()
- onSaveExtraInfo()
-
- val report = Report(bugTitle, bugDescription, deviceInfo, extraInfo)
- val target = GithubTarget("h4h13", "RetroMusicPlayer")
-
- ReportIssueAsyncTask.report(this, report, target, login)
- }
-
- private fun onSaveExtraInfo() {}
-
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == android.R.id.home) {
- onBackPressed()
+ onBackPressedDispatcher.onBackPressed()
}
return super.onOptionsItemSelected(item)
}
- private class ReportIssueAsyncTask private constructor(
- activity: Activity,
- private val report: Report,
- private val target: GithubTarget,
- private val login: GithubLogin
- ) : DialogAsyncTask(activity) {
-
- override fun createDialog(context: Context): Dialog {
- return AlertDialog.Builder(context).show()
- }
-
- @Result
- override fun doInBackground(vararg params: Void): String {
- val client: GitHubClient = if (login.shouldUseApiToken()) {
- GitHubClient().setOAuth2Token(login.apiToken)
- } else {
- GitHubClient().setCredentials(login.username, login.password)
- }
-
- val issue = Issue().setTitle(report.title).setBody(report.description)
- try {
- IssueService(client).createIssue(target.username, target.repository, issue)
- return RESULT_SUCCESS
- } catch (e: RequestException) {
- return when (e.status) {
- STATUS_BAD_CREDENTIALS -> {
- if (login.shouldUseApiToken()) RESULT_INVALID_TOKEN else RESULT_BAD_CREDENTIALS
- }
- STATUS_ISSUES_NOT_ENABLED -> RESULT_ISSUES_NOT_ENABLED
- else -> {
- e.printStackTrace()
- RESULT_UNKNOWN
- }
- }
- } catch (e: IOException) {
- e.printStackTrace()
- return RESULT_UNKNOWN
- }
- }
-
- override fun onPostExecute(@Result result: String) {
- super.onPostExecute(result)
-
- val context = context ?: return
-
- when (result) {
- RESULT_SUCCESS -> tryToFinishActivity()
- RESULT_BAD_CREDENTIALS -> MaterialAlertDialogBuilder(context)
- .setTitle(R.string.bug_report_failed)
- .setMessage(R.string.bug_report_failed_wrong_credentials)
- .setPositiveButton(android.R.string.ok, null)
- .show()
- RESULT_INVALID_TOKEN -> MaterialAlertDialogBuilder(context)
- .setTitle(R.string.bug_report_failed)
- .setMessage(R.string.bug_report_failed_invalid_token)
- .setPositiveButton(android.R.string.ok, null).show()
- RESULT_ISSUES_NOT_ENABLED -> MaterialAlertDialogBuilder(context)
- .setTitle(R.string.bug_report_failed)
- .setMessage(R.string.bug_report_failed_issues_not_available)
- .setPositiveButton(android.R.string.ok, null)
-
- else -> MaterialAlertDialogBuilder(context)
- .setTitle(R.string.bug_report_failed)
- .setMessage(R.string.bug_report_failed_unknown)
- .setPositiveButton(android.R.string.ok) { _, _ -> tryToFinishActivity() }
- .setNegativeButton(android.R.string.cancel) { _, _ -> { tryToFinishActivity() } }
- }
- }
-
- private fun tryToFinishActivity() {
- val context = context
- if (context is Activity && !context.isFinishing) {
- context.finish()
- }
- }
-
-
- companion object {
-
- fun report(
- activity: Activity,
- report: Report,
- target: GithubTarget,
- login: GithubLogin
- ) {
- ReportIssueAsyncTask(activity, report, target, login).execute()
- }
- }
- }
-
companion object {
-
- private const val STATUS_BAD_CREDENTIALS = 401
- private const val STATUS_ISSUES_NOT_ENABLED = 410
- private const val ISSUE_TRACKER_LINK = "https://github.com/h4h13/RetroMusicPlayer"
+ private const val ISSUE_TRACKER_LINK =
+ "https://github.com/MuntashirAkon/Metro/issues/new"
}
}
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/model/DeviceInfo.java b/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/model/DeviceInfo.java
deleted file mode 100644
index e9eee8a23..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/model/DeviceInfo.java
+++ /dev/null
@@ -1,130 +0,0 @@
-package code.name.monkey.retromusic.activities.bugreport.model;
-
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.os.Build;
-
-import androidx.annotation.IntRange;
-
-import java.util.Arrays;
-import java.util.Locale;
-
-import code.name.monkey.retromusic.util.PreferenceUtil;
-
-public class DeviceInfo {
-
- @SuppressLint("NewApi")
- @SuppressWarnings("deprecation")
- private final String[] abis = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ?
- Build.SUPPORTED_ABIS : new String[]{Build.CPU_ABI, Build.CPU_ABI2};
-
- @SuppressLint("NewApi")
- private final String[] abis32Bits = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ?
- Build.SUPPORTED_32_BIT_ABIS : null;
-
- @SuppressLint("NewApi")
- private final String[] abis64Bits = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ?
- Build.SUPPORTED_64_BIT_ABIS : null;
-
- private final String baseTheme;
-
- private final String brand = Build.BRAND;
-
- private final String buildID = Build.DISPLAY;
-
- private final String buildVersion = Build.VERSION.INCREMENTAL;
-
- private final String device = Build.DEVICE;
-
- private final String hardware = Build.HARDWARE;
-
- private final boolean isAdaptive;
-
- private final String manufacturer = Build.MANUFACTURER;
-
- private final String model = Build.MODEL;
-
- private final String nowPlayingTheme;
-
- private final String product = Build.PRODUCT;
-
- private final String releaseVersion = Build.VERSION.RELEASE;
-
- @IntRange(from = 0)
- private final int sdkVersion = Build.VERSION.SDK_INT;
-
- private final int versionCode;
-
- private final String versionName;
- private final String selectedLang;
-
- public DeviceInfo(Context context) {
- PackageInfo packageInfo;
- try {
- packageInfo = context.getPackageManager()
- .getPackageInfo(context.getPackageName(), 0);
- } catch (PackageManager.NameNotFoundException e) {
- packageInfo = null;
- }
- if (packageInfo != null) {
- versionCode = packageInfo.versionCode;
- versionName = packageInfo.versionName;
- } else {
- versionCode = -1;
- versionName = null;
- }
- baseTheme = PreferenceUtil.INSTANCE.getBaseTheme();
- nowPlayingTheme = context.getString(PreferenceUtil.INSTANCE.getNowPlayingScreen().getTitleRes());
- isAdaptive = PreferenceUtil.INSTANCE.isAdaptiveColor();
- selectedLang = PreferenceUtil.INSTANCE.getLanguageCode();
- }
-
- public String toMarkdown() {
- return "Device info:\n"
- + "---\n"
- + "\n"
- + "App version " + versionName + " \n"
- + "App version code " + versionCode + " \n"
- + "Android build version " + buildVersion + " \n"
- + "Android release version " + releaseVersion + " \n"
- + "Android SDK version " + sdkVersion + " \n"
- + "Android build ID " + buildID + " \n"
- + "Device brand " + brand + " \n"
- + "Device manufacturer " + manufacturer + " \n"
- + "Device name " + device + " \n"
- + "Device model " + model + " \n"
- + "Device product name " + product + " \n"
- + "Device hardware name " + hardware + " \n"
- + "ABIs " + Arrays.toString(abis) + " \n"
- + "ABIs (32bit) " + Arrays.toString(abis32Bits) + " \n"
- + "ABIs (64bit) " + Arrays.toString(abis64Bits) + " \n"
- + "Language " + selectedLang + " \n"
- + "
\n";
- }
-
- @Override
- public String toString() {
- return "App version: " + versionName + "\n"
- + "App version code: " + versionCode + "\n"
- + "Android build version: " + buildVersion + "\n"
- + "Android release version: " + releaseVersion + "\n"
- + "Android SDK version: " + sdkVersion + "\n"
- + "Android build ID: " + buildID + "\n"
- + "Device brand: " + brand + "\n"
- + "Device manufacturer: " + manufacturer + "\n"
- + "Device name: " + device + "\n"
- + "Device model: " + model + "\n"
- + "Device product name: " + product + "\n"
- + "Device hardware name: " + hardware + "\n"
- + "ABIs: " + Arrays.toString(abis) + "\n"
- + "ABIs (32bit): " + Arrays.toString(abis32Bits) + "\n"
- + "ABIs (64bit): " + Arrays.toString(abis64Bits) + "\n"
- + "Base theme: " + baseTheme + "\n"
- + "Now playing theme: " + nowPlayingTheme + "\n"
- + "Adaptive: " + isAdaptive + "\n"
- + "System language: " + Locale.getDefault().toLanguageTag() + "\n"
- + "In-App Language: " + selectedLang;
- }
-}
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/model/DeviceInfo.kt b/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/model/DeviceInfo.kt
new file mode 100644
index 000000000..19aff73a2
--- /dev/null
+++ b/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/model/DeviceInfo.kt
@@ -0,0 +1,111 @@
+package code.name.monkey.retromusic.activities.bugreport.model
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.content.pm.PackageManager
+import android.os.Build
+import androidx.annotation.IntRange
+import androidx.appcompat.app.AppCompatDelegate
+import androidx.core.content.pm.PackageInfoCompat
+import code.name.monkey.retromusic.util.PreferenceUtil
+import code.name.monkey.retromusic.util.PreferenceUtil.isAdaptiveColor
+import code.name.monkey.retromusic.util.PreferenceUtil.nowPlayingScreen
+import java.util.*
+
+class DeviceInfo(context: Context) {
+ @SuppressLint("NewApi")
+ private val abis = Build.SUPPORTED_ABIS
+
+ @SuppressLint("NewApi")
+ private val abis32Bits = Build.SUPPORTED_32_BIT_ABIS
+
+ @SuppressLint("NewApi")
+ private val abis64Bits = Build.SUPPORTED_64_BIT_ABIS
+ private val baseTheme: String
+ private val brand = Build.BRAND
+ private val buildID = Build.DISPLAY
+ private val buildVersion = Build.VERSION.INCREMENTAL
+ private val device = Build.DEVICE
+ private val hardware = Build.HARDWARE
+ private val isAdaptive: Boolean
+ private val manufacturer = Build.MANUFACTURER
+ private val model = Build.MODEL
+ private val nowPlayingTheme: String
+ private val product = Build.PRODUCT
+ private val releaseVersion = Build.VERSION.RELEASE
+
+ @IntRange(from = 0)
+ private val sdkVersion = Build.VERSION.SDK_INT
+ private var versionCode = 0L
+ private var versionName: String? = null
+ private val selectedLang: String
+ fun toMarkdown(): String {
+ return """
+ Device info:
+ ---
+
+ App version $versionName
+ App version code $versionCode
+ Android build version $buildVersion
+ Android release version $releaseVersion
+ Android SDK version $sdkVersion
+ Android build ID $buildID
+ Device brand $brand
+ Device manufacturer $manufacturer
+ Device name $device
+ Device model $model
+ Device product name $product
+ Device hardware name $hardware
+ ABIs ${Arrays.toString(abis)}
+ ABIs (32bit) ${Arrays.toString(abis32Bits)}
+ ABIs (64bit) ${Arrays.toString(abis64Bits)}
+ Language $selectedLang
+
+
+ """.trimIndent()
+ }
+
+ override fun toString(): String {
+ return """
+ App version: $versionName
+ App version code: $versionCode
+ Android build version: $buildVersion
+ Android release version: $releaseVersion
+ Android SDK version: $sdkVersion
+ Android build ID: $buildID
+ Device brand: $brand
+ Device manufacturer: $manufacturer
+ Device name: $device
+ Device model: $model
+ Device product name: $product
+ Device hardware name: $hardware
+ ABIs: ${Arrays.toString(abis)}
+ ABIs (32bit): ${Arrays.toString(abis32Bits)}
+ ABIs (64bit): ${Arrays.toString(abis64Bits)}
+ Base theme: $baseTheme
+ Now playing theme: $nowPlayingTheme
+ Adaptive: $isAdaptive
+ System language: ${Locale.getDefault().toLanguageTag()}
+ In-App Language: $selectedLang
+ """.trimIndent()
+ }
+
+ init {
+ val packageInfo = try {
+ context.packageManager.getPackageInfo(context.packageName, 0)
+ } catch (e: PackageManager.NameNotFoundException) {
+ null
+ }
+ if (packageInfo != null) {
+ versionCode = PackageInfoCompat.getLongVersionCode(packageInfo)
+ versionName = packageInfo.versionName
+ } else {
+ versionCode = -1
+ versionName = null
+ }
+ baseTheme = PreferenceUtil.baseTheme
+ nowPlayingTheme = context.getString(nowPlayingScreen.titleRes)
+ isAdaptive = isAdaptiveColor
+ selectedLang = AppCompatDelegate.getApplicationLocales().toLanguageTags()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/model/Report.java b/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/model/Report.java
deleted file mode 100644
index 1da9313bb..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/model/Report.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package code.name.monkey.retromusic.activities.bugreport.model;
-
-
-import code.name.monkey.retromusic.activities.bugreport.model.github.ExtraInfo;
-
-public class Report {
-
- private final String description;
-
- private final DeviceInfo deviceInfo;
-
- private final ExtraInfo extraInfo;
-
- private final String title;
-
- public Report(String title, String description, DeviceInfo deviceInfo, ExtraInfo extraInfo) {
- this.title = title;
- this.description = description;
- this.deviceInfo = deviceInfo;
- this.extraInfo = extraInfo;
- }
-
- public String getDescription() {
- return description + "\n\n"
- + "-\n\n"
- + deviceInfo.toMarkdown() + "\n\n"
- + extraInfo.toMarkdown();
- }
-
- public String getTitle() {
- return title;
- }
-}
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/model/github/ExtraInfo.java b/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/model/github/ExtraInfo.java
deleted file mode 100644
index ec27388cb..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/model/github/ExtraInfo.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package code.name.monkey.retromusic.activities.bugreport.model.github;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-public class ExtraInfo {
-
- private final Map extraInfo = new LinkedHashMap<>();
-
- public void put(String key, String value) {
- extraInfo.put(key, value);
- }
-
- public void put(String key, boolean value) {
- extraInfo.put(key, Boolean.toString(value));
- }
-
- public void put(String key, double value) {
- extraInfo.put(key, Double.toString(value));
- }
-
- public void put(String key, float value) {
- extraInfo.put(key, Float.toString(value));
- }
-
- public void put(String key, long value) {
- extraInfo.put(key, Long.toString(value));
- }
-
- public void put(String key, int value) {
- extraInfo.put(key, Integer.toString(value));
- }
-
- public void put(String key, Object value) {
- extraInfo.put(key, String.valueOf(value));
- }
-
- public void remove(String key) {
- extraInfo.remove(key);
- }
-
- public String toMarkdown() {
- if (extraInfo.isEmpty()) {
- return "";
- }
-
- StringBuilder output = new StringBuilder();
- output.append("Extra info:\n"
- + "---\n"
- + "\n");
- for (String key : extraInfo.keySet()) {
- output.append("")
- .append(key)
- .append(" ")
- .append(extraInfo.get(key))
- .append(" \n");
- }
- output.append("
\n");
-
- return output.toString();
- }
-}
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/model/github/GithubLogin.java b/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/model/github/GithubLogin.java
deleted file mode 100644
index e388249cb..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/model/github/GithubLogin.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package code.name.monkey.retromusic.activities.bugreport.model.github;
-
-import android.text.TextUtils;
-
-public class GithubLogin {
-
- private final String apiToken;
-
- private final String password;
-
- private final String username;
-
- public GithubLogin(String username, String password) {
- this.username = username;
- this.password = password;
- this.apiToken = null;
- }
-
- public GithubLogin(String apiToken) {
- this.username = null;
- this.password = null;
- this.apiToken = apiToken;
- }
-
- public String getApiToken() {
- return apiToken;
- }
-
- public String getPassword() {
- return password;
- }
-
- public String getUsername() {
- return username;
- }
-
- public boolean shouldUseApiToken() {
- return TextUtils.isEmpty(username) || TextUtils.isEmpty(password);
- }
-
-}
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/model/github/GithubTarget.java b/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/model/github/GithubTarget.java
deleted file mode 100644
index 21126d30c..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/activities/bugreport/model/github/GithubTarget.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package code.name.monkey.retromusic.activities.bugreport.model.github;
-
-public class GithubTarget {
-
- private final String repository;
-
- private final String username;
-
- public GithubTarget(String username, String repository) {
- this.username = username;
- this.repository = repository;
- }
-
- public String getRepository() {
- return repository;
- }
-
- public String getUsername() {
- return username;
- }
-}
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/saf/SAFGuideActivity.java b/app/src/main/java/code/name/monkey/retromusic/activities/saf/SAFGuideActivity.java
index a5f2d9083..efd56210e 100644
--- a/app/src/main/java/code/name/monkey/retromusic/activities/saf/SAFGuideActivity.java
+++ b/app/src/main/java/code/name/monkey/retromusic/activities/saf/SAFGuideActivity.java
@@ -24,49 +24,53 @@ import com.heinrichreimersoftware.materialintro.slide.SimpleSlide;
import code.name.monkey.retromusic.R;
-/**
- * Created by hemanths on 2019-07-31.
- */
+/** Created by hemanths on 2019-07-31. */
public class SAFGuideActivity extends IntroActivity {
- public static final int REQUEST_CODE_SAF_GUIDE = 98;
+ public static final int REQUEST_CODE_SAF_GUIDE = 98;
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
- setButtonCtaVisible(false);
- setButtonNextVisible(false);
- setButtonBackVisible(false);
+ setButtonCtaVisible(false);
+ setButtonNextVisible(false);
+ setButtonBackVisible(false);
- setButtonCtaTintMode(BUTTON_CTA_TINT_MODE_TEXT);
+ setButtonCtaTintMode(BUTTON_CTA_TINT_MODE_TEXT);
- String title = String.format(getString(R.string.saf_guide_slide1_title), getString(R.string.app_name));
+ String title =
+ String.format(getString(R.string.saf_guide_slide1_title), getString(R.string.app_name));
- addSlide(new SimpleSlide.Builder()
- .title(title)
- .description(Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1
- ? R.string.saf_guide_slide1_description_before_o : R.string.saf_guide_slide1_description)
- .image(R.drawable.saf_guide_1)
- .background(R.color.md_deep_purple_300)
- .backgroundDark(R.color.md_deep_purple_400)
- .layout(R.layout.fragment_simple_slide_large_image)
- .build());
- addSlide(new SimpleSlide.Builder()
- .title(R.string.saf_guide_slide2_title)
- .description(R.string.saf_guide_slide2_description)
- .image(R.drawable.saf_guide_2)
- .background(R.color.md_deep_purple_500)
- .backgroundDark(R.color.md_deep_purple_600)
- .layout(R.layout.fragment_simple_slide_large_image)
- .build());
- addSlide(new SimpleSlide.Builder()
- .title(R.string.saf_guide_slide3_title)
- .description(R.string.saf_guide_slide3_description)
- .image(R.drawable.saf_guide_3)
- .background(R.color.md_deep_purple_700)
- .backgroundDark(R.color.md_deep_purple_800)
- .layout(R.layout.fragment_simple_slide_large_image)
- .build());
- }
+ addSlide(
+ new SimpleSlide.Builder()
+ .title(title)
+ .description(
+ Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1
+ ? R.string.saf_guide_slide1_description_before_o
+ : R.string.saf_guide_slide1_description)
+ .image(R.drawable.saf_guide_1)
+ .background(code.name.monkey.appthemehelper.R.color.md_deep_purple_300)
+ .backgroundDark(code.name.monkey.appthemehelper.R.color.md_deep_purple_400)
+ .layout(R.layout.fragment_simple_slide_large_image)
+ .build());
+ addSlide(
+ new SimpleSlide.Builder()
+ .title(R.string.saf_guide_slide2_title)
+ .description(R.string.saf_guide_slide2_description)
+ .image(R.drawable.saf_guide_2)
+ .background(code.name.monkey.appthemehelper.R.color.md_deep_purple_500)
+ .backgroundDark(code.name.monkey.appthemehelper.R.color.md_deep_purple_600)
+ .layout(R.layout.fragment_simple_slide_large_image)
+ .build());
+ addSlide(
+ new SimpleSlide.Builder()
+ .title(R.string.saf_guide_slide3_title)
+ .description(R.string.saf_guide_slide3_description)
+ .image(R.drawable.saf_guide_3)
+ .background(code.name.monkey.appthemehelper.R.color.md_deep_purple_700)
+ .backgroundDark(code.name.monkey.appthemehelper.R.color.md_deep_purple_800)
+ .layout(R.layout.fragment_simple_slide_large_image)
+ .build());
+ }
}
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/saf/SAFRequestActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/saf/SAFRequestActivity.kt
new file mode 100644
index 000000000..1b389b9d2
--- /dev/null
+++ b/app/src/main/java/code/name/monkey/retromusic/activities/saf/SAFRequestActivity.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2021 Bartlomiej Uliasz.
+ *
+ * Licensed under the GNU General Public License v3
+ *
+ * This is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by
+ * the Free Software Foundation either version 3 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ */
+package code.name.monkey.retromusic.activities.saf
+
+import android.app.Activity
+import android.content.Intent
+import android.os.Bundle
+import code.name.monkey.retromusic.activities.saf.SAFGuideActivity.REQUEST_CODE_SAF_GUIDE
+import code.name.monkey.retromusic.util.SAFUtil
+
+/** Created by buliasz on 2021-02-07. */
+class SAFRequestActivity : Activity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ val intent = Intent(this, code.name.monkey.retromusic.activities.saf.SAFGuideActivity::class.java)
+ startActivityForResult(intent, REQUEST_CODE_SAF_GUIDE)
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
+ super.onActivityResult(requestCode, resultCode, intent)
+ when (requestCode) {
+ REQUEST_CODE_SAF_GUIDE -> {
+ SAFUtil.openTreePicker(this)
+ }
+ SAFUtil.REQUEST_SAF_PICK_TREE -> {
+ if (resultCode == RESULT_OK) {
+ SAFUtil.saveTreeUri(this, intent)
+ }
+ finish()
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AbsTagEditorActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AbsTagEditorActivity.kt
index 8b49a57c7..3a9ca4e4b 100755
--- a/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AbsTagEditorActivity.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AbsTagEditorActivity.kt
@@ -1,52 +1,83 @@
+/*
+ * Copyright (c) 2020 Hemanth Savarla.
+ *
+ * Licensed under the GNU General Public License v3
+ *
+ * This is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ */
package code.name.monkey.retromusic.activities.tageditor
import android.app.Activity
import android.app.SearchManager
import android.content.Intent
-import android.content.res.ColorStateList
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
-import android.os.Build
import android.os.Bundle
+import android.provider.MediaStore
import android.util.Log
+import android.view.LayoutInflater
import android.view.MenuItem
-import android.view.View
import android.view.animation.OvershootInterpolator
+import android.widget.ImageView
+import androidx.activity.result.ActivityResultLauncher
+import androidx.activity.result.IntentSenderRequest
+import androidx.activity.result.PickVisualMediaRequest
+import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AlertDialog
-import code.name.monkey.appthemehelper.ThemeStore
-import code.name.monkey.appthemehelper.util.ATHUtil
-import code.name.monkey.appthemehelper.util.ColorUtil
-import code.name.monkey.appthemehelper.util.MaterialValueHelper
-import code.name.monkey.appthemehelper.util.TintHelper
+import androidx.lifecycle.lifecycleScope
+import androidx.viewbinding.ViewBinding
+import code.name.monkey.appthemehelper.util.VersionUtils
import code.name.monkey.retromusic.R
-import code.name.monkey.retromusic.R.drawable
import code.name.monkey.retromusic.activities.base.AbsBaseActivity
-import code.name.monkey.retromusic.activities.saf.SAFGuideActivity
-import code.name.monkey.retromusic.util.RetroUtil
-import code.name.monkey.retromusic.util.SAFUtil
+import code.name.monkey.retromusic.extensions.accentColor
+import code.name.monkey.retromusic.extensions.colorButtons
+import code.name.monkey.retromusic.extensions.hideSoftKeyboard
+import code.name.monkey.retromusic.extensions.setTaskDescriptionColorAuto
+import code.name.monkey.retromusic.model.ArtworkInfo
+import code.name.monkey.retromusic.model.AudioTagInfo
+import code.name.monkey.retromusic.repository.Repository
+import code.name.monkey.retromusic.util.logD
+import code.name.monkey.retromusic.util.logE
import com.google.android.material.button.MaterialButton
import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import kotlinx.android.synthetic.main.activity_album_tag_editor.*
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.launch
import org.jaudiotagger.audio.AudioFile
import org.jaudiotagger.audio.AudioFileIO
import org.jaudiotagger.tag.FieldKey
+import org.koin.android.ext.android.inject
import java.io.File
-import java.util.*
-abstract class AbsTagEditorActivity : AbsBaseActivity() {
+abstract class AbsTagEditorActivity : AbsBaseActivity() {
+ abstract val editorImage: ImageView
+ val repository by inject()
- protected var id: Int = 0
+ lateinit var saveFab: MaterialButton
+ protected var id: Long = 0
private set
private var paletteColorPrimary: Int = 0
- private var isInNoImageMode: Boolean = false
private var songPaths: List? = null
- lateinit var saveFab: MaterialButton
-
private var savedSongPaths: List? = null
private val currentSongPath: String? = null
private var savedTags: Map? = null
private var savedArtworkInfo: ArtworkInfo? = null
+ private var _binding: VB? = null
+ protected val binding: VB get() = _binding!!
+ private var cacheFiles = listOf()
+
+ abstract val bindingInflater: (LayoutInflater) -> VB
+
+ private lateinit var launcher: ActivityResultLauncher
+
+ protected abstract fun loadImageFromFile(selectedFile: Uri?)
protected val show: AlertDialog
get() =
@@ -59,14 +90,16 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() {
2 -> deleteImage()
}
}
+ .setNegativeButton(R.string.action_cancel, null)
.show()
- protected abstract val contentViewLayout: Int
+ .colorButtons()
internal val albumArtist: String?
get() {
return try {
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.ALBUM_ARTIST)
- } catch (ignored: Exception) {
+ } catch (e: Exception) {
+ logE(e)
null
}
}
@@ -75,7 +108,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() {
get() {
return try {
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.TITLE)
- } catch (ignored: Exception) {
+ } catch (e: Exception) {
+ logE(e)
null
}
}
@@ -83,7 +117,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() {
get() {
return try {
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.COMPOSER)
- } catch (ignored: Exception) {
+ } catch (e: Exception) {
+ logE(e)
null
}
}
@@ -92,7 +127,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() {
get() {
return try {
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.ALBUM)
- } catch (ignored: Exception) {
+ } catch (e: Exception) {
+ logE(e)
null
}
}
@@ -101,7 +137,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() {
get() {
return try {
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.ARTIST)
- } catch (ignored: Exception) {
+ } catch (e: Exception) {
+ logE(e)
null
}
}
@@ -110,7 +147,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() {
get() {
return try {
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.ALBUM_ARTIST)
- } catch (ignored: Exception) {
+ } catch (e: Exception) {
+ logE(e)
null
}
}
@@ -119,7 +157,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() {
get() {
return try {
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.GENRE)
- } catch (ignored: Exception) {
+ } catch (e: Exception) {
+ logE(e)
null
}
}
@@ -128,7 +167,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() {
get() {
return try {
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.YEAR)
- } catch (ignored: Exception) {
+ } catch (e: Exception) {
+ logE(e)
null
}
}
@@ -137,7 +177,18 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() {
get() {
return try {
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.TRACK)
- } catch (ignored: Exception) {
+ } catch (e: Exception) {
+ logE(e)
+ null
+ }
+ }
+
+ protected val discNumber: String?
+ get() {
+ return try {
+ getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.DISC_NO)
+ } catch (e: Exception) {
+ logE(e)
null
}
}
@@ -146,7 +197,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() {
get() {
return try {
getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.LYRICS)
- } catch (ignored: Exception) {
+ } catch (e: Exception) {
+ logE(e)
null
}
}
@@ -164,62 +216,58 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() {
)
}
return null
- } catch (ignored: Exception) {
+ } catch (e: Exception) {
+ logE(e)
return null
}
}
+ private val pickArtworkImage =
+ registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri ->
+ loadImageFromFile(uri)
+ }
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- setContentView(contentViewLayout)
+ _binding = bindingInflater.invoke(layoutInflater)
+ setContentView(binding.root)
+ setTaskDescriptionColorAuto()
saveFab = findViewById(R.id.saveTags)
getIntentExtras()
songPaths = getSongPaths()
+ logD(songPaths?.size)
if (songPaths!!.isEmpty()) {
finish()
- return
}
-
setUpViews()
-
- setStatusbarColorAuto()
- setNavigationbarColorAuto()
- setTaskDescriptionColorAuto()
+ launcher = registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) {
+ if (it.resultCode == Activity.RESULT_OK) {
+ writeToFiles(getSongUris(), cacheFiles)
+ }
+ }
}
private fun setUpViews() {
- setUpScrollView()
setUpFab()
setUpImageView()
}
- private fun setUpScrollView() {
- //observableScrollView.setScrollViewCallbacks(observableScrollViewCallbacks);
- }
-
private lateinit var items: List
private fun setUpImageView() {
loadCurrentImage()
items = listOf(
- getString(code.name.monkey.retromusic.R.string.pick_from_local_storage),
- getString(code.name.monkey.retromusic.R.string.web_search),
- getString(code.name.monkey.retromusic.R.string.remove_cover)
+ getString(R.string.pick_from_local_storage),
+ getString(R.string.web_search),
+ getString(R.string.remove_cover)
)
- editorImage?.setOnClickListener { show }
+ editorImage.setOnClickListener { show }
}
private fun startImagePicker() {
- val intent = Intent(Intent.ACTION_GET_CONTENT)
- intent.type = "image/*"
- startActivityForResult(
- Intent.createChooser(
- intent,
- getString(code.name.monkey.retromusic.R.string.pick_from_local_storage)
- ), REQUEST_CODE_SELECT_IMAGE
- )
+ pickArtworkImage.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly))
}
protected abstract fun loadCurrentImage()
@@ -229,26 +277,12 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() {
protected abstract fun deleteImage()
private fun setUpFab() {
- saveFab.backgroundTintList = ColorStateList.valueOf(ThemeStore.accentColor(this))
- ColorStateList.valueOf(
- MaterialValueHelper.getPrimaryTextColor(
- this,
- ColorUtil.isColorLight(
- ThemeStore.accentColor(
- this
- )
- )
- )
- ).apply {
- saveFab.setTextColor(this)
- saveFab.iconTint = this
- }
+ saveFab.accentColor()
saveFab.apply {
scaleX = 0f
scaleY = 0f
isEnabled = false
setOnClickListener { save() }
- TintHelper.setTintAuto(this, ThemeStore.accentColor(this@AbsTagEditorActivity), true)
}
}
@@ -257,12 +291,14 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() {
private fun getIntentExtras() {
val intentExtras = intent.extras
if (intentExtras != null) {
- id = intentExtras.getInt(EXTRA_ID)
+ id = intentExtras.getLong(EXTRA_ID)
}
}
protected abstract fun getSongPaths(): List
+ protected abstract fun getSongUris(): List
+
protected fun searchWebFor(vararg keys: String) {
val stringBuilder = StringBuilder()
for (key in keys) {
@@ -279,27 +315,13 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> {
- super.onBackPressed()
+ onBackPressedDispatcher.onBackPressed()
return true
}
}
return super.onOptionsItemSelected(item)
}
- protected fun setNoImageMode() {
- isInNoImageMode = true
- imageContainer?.visibility = View.GONE
- editorImage?.visibility = View.GONE
- editorImage?.isEnabled = false
-
- setColors(
- intent.getIntExtra(
- EXTRA_PALETTE,
- ATHUtil.resolveColor(this, R.attr.colorPrimary)
- )
- )
- }
-
protected fun dataChanged() {
showFab()
}
@@ -318,7 +340,7 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() {
protected fun setImageBitmap(bitmap: Bitmap?, bgColor: Int) {
if (bitmap == null) {
- editorImage.setImageResource(drawable.default_audio_art)
+ editorImage.setImageResource(R.drawable.default_audio_art)
} else {
editorImage.setImageBitmap(bitmap)
}
@@ -330,86 +352,106 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() {
}
protected fun writeValuesToFiles(
- fieldKeyValueMap: Map, artworkInfo: ArtworkInfo?
+ fieldKeyValueMap: Map,
+ artworkInfo: ArtworkInfo?
) {
- RetroUtil.hideSoftKeyboard(this)
+ hideSoftKeyboard()
hideFab()
-
- savedSongPaths = getSongPaths()
- savedTags = fieldKeyValueMap
- savedArtworkInfo = artworkInfo
-
- if (!SAFUtil.isSAFRequired(savedSongPaths)) {
- writeTags(savedSongPaths)
- } else {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- if (SAFUtil.isSDCardAccessGranted(this)) {
- writeTags(savedSongPaths)
- } else {
- startActivityForResult(
- Intent(this, SAFGuideActivity::class.java),
- SAFGuideActivity.REQUEST_CODE_SAF_GUIDE
+ logD(fieldKeyValueMap)
+ GlobalScope.launch {
+ if (VersionUtils.hasR()) {
+ cacheFiles = TagWriter.writeTagsToFilesR(
+ this@AbsTagEditorActivity, AudioTagInfo(
+ songPaths,
+ fieldKeyValueMap,
+ artworkInfo
)
+ )
+
+ if (cacheFiles.isNotEmpty()) {
+ val pendingIntent =
+ MediaStore.createWriteRequest(contentResolver, getSongUris())
+ launcher.launch(IntentSenderRequest.Builder(pendingIntent).build())
}
+ } else {
+ TagWriter.writeTagsToFiles(
+ this@AbsTagEditorActivity, AudioTagInfo(
+ songPaths,
+ fieldKeyValueMap,
+ artworkInfo
+ )
+ )
}
}
}
private fun writeTags(paths: List?) {
- WriteTagsAsyncTask(this).execute(
- WriteTagsAsyncTask.LoadingInfo(
- paths,
- savedTags,
- savedArtworkInfo
- )
- )
- }
+ GlobalScope.launch {
+ if (VersionUtils.hasR()) {
+ cacheFiles = TagWriter.writeTagsToFilesR(
+ this@AbsTagEditorActivity, AudioTagInfo(
+ paths,
+ savedTags,
+ savedArtworkInfo
+ )
+ )
+ val pendingIntent = MediaStore.createWriteRequest(contentResolver, getSongUris())
- override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
- super.onActivityResult(requestCode, resultCode, intent)
- when (requestCode) {
- REQUEST_CODE_SELECT_IMAGE -> if (resultCode == Activity.RESULT_OK) {
- intent?.data?.let {
- loadImageFromFile(it)
- }
- }
- SAFGuideActivity.REQUEST_CODE_SAF_GUIDE -> {
- SAFUtil.openTreePicker(this)
- }
- SAFUtil.REQUEST_SAF_PICK_TREE -> {
- if (resultCode == Activity.RESULT_OK) {
- SAFUtil.saveTreeUri(this, intent)
- writeTags(savedSongPaths)
- }
- }
- SAFUtil.REQUEST_SAF_PICK_FILE -> {
- if (resultCode == Activity.RESULT_OK) {
- writeTags(Collections.singletonList(currentSongPath + SAFUtil.SEPARATOR + intent!!.dataString))
- }
+ launcher.launch(IntentSenderRequest.Builder(pendingIntent).build())
+ } else {
+ TagWriter.writeTagsToFiles(
+ this@AbsTagEditorActivity, AudioTagInfo(
+ paths,
+ savedTags,
+ savedArtworkInfo
+ )
+ )
}
}
}
- protected abstract fun loadImageFromFile(selectedFile: Uri?)
+ private lateinit var audioFile: AudioFile
private fun getAudioFile(path: String): AudioFile {
return try {
- AudioFileIO.read(File(path))
+ if (!this::audioFile.isInitialized) {
+ audioFile = AudioFileIO.read(File(path))
+ }
+ audioFile
} catch (e: Exception) {
Log.e(TAG, "Could not read audio file $path", e)
AudioFile()
}
}
- class ArtworkInfo constructor(val albumId: Int, val artwork: Bitmap?)
+ private fun writeToFiles(songUris: List, cacheFiles: List) {
+ if (cacheFiles.size == songUris.size) {
+ for (i in cacheFiles.indices) {
+ contentResolver.openOutputStream(songUris[i])?.use { output ->
+ cacheFiles[i].inputStream().use { input ->
+ input.copyTo(output)
+ }
+ }
+ }
+ }
+ lifecycleScope.launch {
+ TagWriter.scan(this@AbsTagEditorActivity, getSongPaths())
+ }
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ // Delete Cache Files
+ cacheFiles.forEach { file ->
+ file.delete()
+ }
+ }
companion object {
-
const val EXTRA_ID = "extra_id"
const val EXTRA_PALETTE = "extra_palette"
private val TAG = AbsTagEditorActivity::class.java.simpleName
private const val REQUEST_CODE_SELECT_IMAGE = 1000
}
-
}
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AlbumTagEditorActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AlbumTagEditorActivity.kt
index b66a0a496..2c9013657 100755
--- a/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AlbumTagEditorActivity.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AlbumTagEditorActivity.kt
@@ -1,3 +1,17 @@
+/*
+ * Copyright (c) 2020 Hemanth Savarla.
+ *
+ * Licensed under the GNU General Public License v3
+ *
+ * This is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ */
package code.name.monkey.retromusic.activities.tageditor
import android.app.Activity
@@ -8,31 +22,36 @@ import android.graphics.Color
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Bundle
-import android.text.Editable
-import android.text.TextWatcher
import android.transition.Slide
+import android.view.LayoutInflater
+import android.widget.ImageView
import android.widget.Toast
-import code.name.monkey.appthemehelper.util.ATHUtil
-import code.name.monkey.appthemehelper.util.MaterialUtil
+import androidx.core.widget.doAfterTextChanged
+import code.name.monkey.appthemehelper.util.MaterialValueHelper
import code.name.monkey.retromusic.R
-import code.name.monkey.retromusic.extensions.appHandleColor
-import code.name.monkey.retromusic.glide.palette.BitmapPaletteTranscoder
+import code.name.monkey.retromusic.databinding.ActivityAlbumTagEditorBinding
+import code.name.monkey.retromusic.extensions.*
+import code.name.monkey.retromusic.glide.RetroGlideExtension.asBitmapPalette
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper
-import code.name.monkey.retromusic.loaders.AlbumLoader
+import code.name.monkey.retromusic.model.ArtworkInfo
+import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.ImageUtil
+import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.RetroColorUtil.generatePalette
import code.name.monkey.retromusic.util.RetroColorUtil.getColor
+import code.name.monkey.retromusic.util.logD
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
-import com.bumptech.glide.request.animation.GlideAnimation
-import com.bumptech.glide.request.target.SimpleTarget
-import kotlinx.android.synthetic.main.activity_album_tag_editor.*
+import com.bumptech.glide.request.target.ImageViewTarget
+import com.bumptech.glide.request.transition.Transition
+import com.google.android.material.shape.MaterialShapeDrawable
import org.jaudiotagger.tag.FieldKey
import java.util.*
-class AlbumTagEditorActivity : AbsTagEditorActivity(), TextWatcher {
- override val contentViewLayout: Int
- get() = R.layout.activity_album_tag_editor
+class AlbumTagEditorActivity : AbsTagEditorActivity() {
+
+ override val bindingInflater: (LayoutInflater) -> ActivityAlbumTagEditorBinding =
+ ActivityAlbumTagEditorBinding::inflate
private fun windowEnterTransition() {
val slide = Slide()
@@ -44,54 +63,19 @@ class AlbumTagEditorActivity : AbsTagEditorActivity(), TextWatcher {
window.enterTransition = slide
}
- override fun loadImageFromFile(selectedFileUri: Uri?) {
-
- Glide.with(this@AlbumTagEditorActivity).load(selectedFileUri).asBitmap()
- .transcode(BitmapPaletteTranscoder(this), BitmapPaletteWrapper::class.java)
- .diskCacheStrategy(DiskCacheStrategy.NONE).skipMemoryCache(true)
- .into(object : SimpleTarget() {
- override fun onResourceReady(
- resource: BitmapPaletteWrapper?,
- glideAnimation: GlideAnimation?
- ) {
- getColor(resource?.palette, Color.TRANSPARENT)
- albumArtBitmap = resource?.bitmap?.let { ImageUtil.resizeBitmap(it, 2048) }
- setImageBitmap(
- albumArtBitmap,
- getColor(
- resource?.palette,
- ATHUtil.resolveColor(
- this@AlbumTagEditorActivity,
- R.attr.defaultFooterColor
- )
- )
- )
- deleteAlbumArt = false
- dataChanged()
- setResult(Activity.RESULT_OK)
- }
-
- override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) {
- super.onLoadFailed(e, errorDrawable)
- Toast.makeText(this@AlbumTagEditorActivity, e.toString(), Toast.LENGTH_LONG)
- .show()
- }
- })
- }
-
private var albumArtBitmap: Bitmap? = null
private var deleteAlbumArt: Boolean = false
private fun setupToolbar() {
- toolbar.setBackgroundColor(ATHUtil.resolveColor(this, R.attr.colorSurface))
- setSupportActionBar(toolbar)
+ setSupportActionBar(binding.toolbar)
+ binding.appBarLayout?.statusBarForeground =
+ MaterialShapeDrawable.createWithElevationOverlay(this)
}
override fun onCreate(savedInstanceState: Bundle?) {
- setDrawUnderStatusBar()
super.onCreate(savedInstanceState)
window.sharedElementsUseOverlay = true
- imageContainer?.transitionName = getString(R.string.transition_album_art)
+ binding.imageContainer.transitionName = getString(R.string.transition_album_art)
windowEnterTransition()
setUpViews()
setupToolbar()
@@ -100,22 +84,23 @@ class AlbumTagEditorActivity : AbsTagEditorActivity(), TextWatcher {
private fun setUpViews() {
fillViewsWithFileTags()
- MaterialUtil.setTint(yearContainer, false)
- MaterialUtil.setTint(genreContainer, false)
- MaterialUtil.setTint(albumTitleContainer, false)
- MaterialUtil.setTint(albumArtistContainer, false)
+ binding.yearContainer.setTint(false)
+ binding.genreContainer.setTint(false)
+ binding.albumTitleContainer.setTint(false)
+ binding.albumArtistContainer.setTint(false)
- albumText.appHandleColor().addTextChangedListener(this)
- albumArtistText.appHandleColor().addTextChangedListener(this)
- genreTitle.appHandleColor().addTextChangedListener(this)
- yearTitle.appHandleColor().addTextChangedListener(this)
+ binding.albumText.appHandleColor().doAfterTextChanged { dataChanged() }
+ binding.albumArtistText.appHandleColor().doAfterTextChanged { dataChanged() }
+ binding.genreTitle.appHandleColor().doAfterTextChanged { dataChanged() }
+ binding.yearTitle.appHandleColor().doAfterTextChanged { dataChanged() }
}
private fun fillViewsWithFileTags() {
- albumText.setText(albumTitle)
- albumArtistText.setText(albumArtistName)
- genreTitle.setText(genreName)
- yearTitle.setText(songYear)
+ binding.albumText.setText(albumTitle)
+ binding.albumArtistText.setText(albumArtistName)
+ binding.genreTitle.setText(genreName)
+ binding.yearTitle.setText(songYear)
+ logD(albumTitle + albumArtistName)
}
override fun loadCurrentImage() {
@@ -124,73 +109,109 @@ class AlbumTagEditorActivity : AbsTagEditorActivity(), TextWatcher {
bitmap,
getColor(
generatePalette(bitmap),
- ATHUtil.resolveColor(this, R.attr.defaultFooterColor)
+ defaultFooterColor()
)
)
deleteAlbumArt = false
}
private fun toastLoadingFailed() {
- Toast.makeText(
- this@AlbumTagEditorActivity,
- R.string.could_not_download_album_cover,
- Toast.LENGTH_SHORT
- ).show()
+ showToast(R.string.could_not_download_album_cover)
}
override fun searchImageOnWeb() {
- searchWebFor(albumText.text.toString(), albumArtistText.text.toString())
+ searchWebFor(binding.albumText.text.toString(), binding.albumArtistText.text.toString())
}
override fun deleteImage() {
setImageBitmap(
BitmapFactory.decodeResource(resources, R.drawable.default_audio_art),
- ATHUtil.resolveColor(this, R.attr.defaultFooterColor)
+ defaultFooterColor()
)
deleteAlbumArt = true
dataChanged()
}
+ override fun loadImageFromFile(selectedFile: Uri?) {
+ Glide.with(this@AlbumTagEditorActivity)
+ .asBitmapPalette()
+ .load(selectedFile)
+ .diskCacheStrategy(DiskCacheStrategy.NONE).skipMemoryCache(true)
+ .into(object : ImageViewTarget(binding.editorImage) {
+ override fun onResourceReady(
+ resource: BitmapPaletteWrapper,
+ transition: Transition?
+ ) {
+ getColor(resource.palette, Color.TRANSPARENT)
+ albumArtBitmap = resource.bitmap?.let { ImageUtil.resizeBitmap(it, 2048) }
+ setImageBitmap(
+ albumArtBitmap,
+ getColor(
+ resource.palette,
+ defaultFooterColor()
+ )
+ )
+ deleteAlbumArt = false
+ dataChanged()
+ setResult(Activity.RESULT_OK)
+ }
+
+ override fun onLoadFailed(errorDrawable: Drawable?) {
+ super.onLoadFailed(errorDrawable)
+ showToast(R.string.error_load_failed, Toast.LENGTH_LONG)
+ }
+
+ override fun setResource(resource: BitmapPaletteWrapper?) {}
+ })
+ }
+
override fun save() {
val fieldKeyValueMap = EnumMap(FieldKey::class.java)
- fieldKeyValueMap[FieldKey.ALBUM] = albumText.text.toString()
- //android seems not to recognize album_artist field so we additionally write the normal artist field
- fieldKeyValueMap[FieldKey.ARTIST] = albumArtistText.text.toString()
- fieldKeyValueMap[FieldKey.ALBUM_ARTIST] = albumArtistText.text.toString()
- fieldKeyValueMap[FieldKey.GENRE] = genreTitle.text.toString()
- fieldKeyValueMap[FieldKey.YEAR] = yearTitle.text.toString()
+ fieldKeyValueMap[FieldKey.ALBUM] = binding.albumText.text.toString()
+ // android seems not to recognize album_artist field so we additionally write the normal artist field
+ fieldKeyValueMap[FieldKey.ARTIST] = binding.albumArtistText.text.toString()
+ fieldKeyValueMap[FieldKey.ALBUM_ARTIST] = binding.albumArtistText.text.toString()
+ fieldKeyValueMap[FieldKey.GENRE] = binding.genreTitle.text.toString()
+ fieldKeyValueMap[FieldKey.YEAR] = binding.yearTitle.text.toString()
writeValuesToFiles(
fieldKeyValueMap,
- if (deleteAlbumArt) AbsTagEditorActivity.ArtworkInfo(id, null)
- else if (albumArtBitmap == null) null else ArtworkInfo(id, albumArtBitmap!!)
+ when {
+ deleteAlbumArt -> ArtworkInfo(id, null)
+ albumArtBitmap == null -> null
+ else -> ArtworkInfo(id, albumArtBitmap!!)
+ }
)
}
override fun getSongPaths(): List {
- val songs = AlbumLoader.getAlbum(this, id).songs
- val paths = ArrayList(songs!!.size)
- for (song in songs) {
- paths.add(song.data)
- }
- return paths
+ return repository.albumById(id).songs
+ .map(Song::data)
}
- override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
- }
-
- override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
- }
-
- override fun afterTextChanged(s: Editable) {
- dataChanged()
+ override fun getSongUris(): List = repository.albumById(id).songs.map {
+ MusicUtil.getSongFileUri(it.id)
}
override fun setColors(color: Int) {
super.setColors(color)
saveFab.backgroundTintList = ColorStateList.valueOf(color)
+ saveFab.backgroundTintList = ColorStateList.valueOf(color)
+ ColorStateList.valueOf(
+ MaterialValueHelper.getPrimaryTextColor(
+ this,
+ color.isColorLight
+ )
+ ).also {
+ saveFab.iconTint = it
+ saveFab.setTextColor(it)
+ }
}
+
+ override val editorImage: ImageView
+ get() = binding.editorImage
+
companion object {
val TAG: String = AlbumTagEditorActivity::class.java.simpleName
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/SongTagEditorActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/SongTagEditorActivity.kt
index d99bb70cd..93dd8a44f 100755
--- a/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/SongTagEditorActivity.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/SongTagEditorActivity.kt
@@ -1,112 +1,214 @@
+/*
+ * Copyright (c) 2020 Hemanth Savarla.
+ *
+ * Licensed under the GNU General Public License v3
+ *
+ * This is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ */
package code.name.monkey.retromusic.activities.tageditor
+import android.annotation.SuppressLint
+import android.app.Activity
+import android.content.res.ColorStateList
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
+import android.graphics.Color
+import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Bundle
-import android.text.Editable
-import android.text.TextWatcher
-import code.name.monkey.appthemehelper.util.ATHUtil
-import code.name.monkey.appthemehelper.util.MaterialUtil
+import android.view.LayoutInflater
+import android.widget.ImageView
+import android.widget.Toast
+import androidx.core.widget.doAfterTextChanged
+import code.name.monkey.appthemehelper.util.MaterialValueHelper
import code.name.monkey.retromusic.R
-import code.name.monkey.retromusic.extensions.appHandleColor
-import code.name.monkey.retromusic.loaders.SongLoader
-import kotlinx.android.synthetic.main.activity_song_tag_editor.*
+import code.name.monkey.retromusic.databinding.ActivitySongTagEditorBinding
+import code.name.monkey.retromusic.extensions.*
+import code.name.monkey.retromusic.glide.RetroGlideExtension.asBitmapPalette
+import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper
+import code.name.monkey.retromusic.model.ArtworkInfo
+import code.name.monkey.retromusic.repository.SongRepository
+import code.name.monkey.retromusic.util.ImageUtil
+import code.name.monkey.retromusic.util.MusicUtil
+import code.name.monkey.retromusic.util.RetroColorUtil
+import code.name.monkey.retromusic.util.logD
+import com.bumptech.glide.Glide
+import com.bumptech.glide.load.engine.DiskCacheStrategy
+import com.bumptech.glide.request.target.ImageViewTarget
+import com.bumptech.glide.request.transition.Transition
+import com.google.android.material.shape.MaterialShapeDrawable
import org.jaudiotagger.tag.FieldKey
+import org.koin.android.ext.android.inject
import java.util.*
-class SongTagEditorActivity : AbsTagEditorActivity(), TextWatcher {
+class SongTagEditorActivity : AbsTagEditorActivity() {
- override val contentViewLayout: Int
- get() = R.layout.activity_song_tag_editor
+ override val bindingInflater: (LayoutInflater) -> ActivitySongTagEditorBinding =
+ ActivitySongTagEditorBinding::inflate
+
+
+ private val songRepository by inject()
+
+ private var albumArtBitmap: Bitmap? = null
+ private var deleteAlbumArt: Boolean = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
-
- setNoImageMode()
setUpViews()
- toolbar.setBackgroundColor(ATHUtil.resolveColor(this, R.attr.colorSurface))
- setSupportActionBar(toolbar)
+ setSupportActionBar(binding.toolbar)
+ binding.appBarLayout?.statusBarForeground =
+ MaterialShapeDrawable.createWithElevationOverlay(this)
}
+ @SuppressLint("ClickableViewAccessibility")
private fun setUpViews() {
fillViewsWithFileTags()
- MaterialUtil.setTint(songTextContainer, false)
- MaterialUtil.setTint(composerContainer, false)
- MaterialUtil.setTint(albumTextContainer, false)
- MaterialUtil.setTint(artistContainer, false)
- MaterialUtil.setTint(albumArtistContainer, false)
- MaterialUtil.setTint(yearContainer, false)
- MaterialUtil.setTint(genreContainer, false)
- MaterialUtil.setTint(trackNumberContainer, false)
- MaterialUtil.setTint(lyricsContainer, false)
+ binding.songTextContainer.setTint(false)
+ binding.composerContainer.setTint(false)
+ binding.albumTextContainer.setTint(false)
+ binding.artistContainer.setTint(false)
+ binding.albumArtistContainer.setTint(false)
+ binding.yearContainer.setTint(false)
+ binding.genreContainer.setTint(false)
+ binding.trackNumberContainer.setTint(false)
+ binding.discNumberContainer.setTint(false)
+ binding.lyricsContainer.setTint(false)
- songText.appHandleColor().addTextChangedListener(this)
- albumText.appHandleColor().addTextChangedListener(this)
- albumArtistText.appHandleColor().addTextChangedListener(this)
- artistText.appHandleColor().addTextChangedListener(this)
- genreText.appHandleColor().addTextChangedListener(this)
- yearText.appHandleColor().addTextChangedListener(this)
- trackNumberText.appHandleColor().addTextChangedListener(this)
- lyricsText.appHandleColor().addTextChangedListener(this)
- songComposerText.appHandleColor().addTextChangedListener(this)
+ binding.songText.appHandleColor().doAfterTextChanged { dataChanged() }
+ binding.albumText.appHandleColor().doAfterTextChanged { dataChanged() }
+ binding.albumArtistText.appHandleColor().doAfterTextChanged { dataChanged() }
+ binding.artistText.appHandleColor().doAfterTextChanged { dataChanged() }
+ binding.genreText.appHandleColor().doAfterTextChanged { dataChanged() }
+ binding.yearText.appHandleColor().doAfterTextChanged { dataChanged() }
+ binding.trackNumberText.appHandleColor().doAfterTextChanged { dataChanged() }
+ binding.discNumberText.appHandleColor().doAfterTextChanged { dataChanged() }
+ binding.lyricsText.appHandleColor().doAfterTextChanged { dataChanged() }
+ binding.songComposerText.appHandleColor().doAfterTextChanged { dataChanged() }
}
private fun fillViewsWithFileTags() {
- songText.setText(songTitle)
- albumArtistText.setText(albumArtist)
- albumText.setText(albumTitle)
- artistText.setText(artistName)
- genreText.setText(genreName)
- yearText.setText(songYear)
- trackNumberText.setText(trackNumber)
- lyricsText.setText(lyrics)
- songComposerText.setText(composer)
+ binding.songText.setText(songTitle)
+ binding.albumArtistText.setText(albumArtist)
+ binding.albumText.setText(albumTitle)
+ binding.artistText.setText(artistName)
+ binding.genreText.setText(genreName)
+ binding.yearText.setText(songYear)
+ binding.trackNumberText.setText(trackNumber)
+ binding.discNumberText.setText(discNumber)
+ binding.lyricsText.setText(lyrics)
+ binding.songComposerText.setText(composer)
+ logD(songTitle + songYear)
}
override fun loadCurrentImage() {
+ val bitmap = albumArt
+ setImageBitmap(
+ bitmap,
+ RetroColorUtil.getColor(
+ RetroColorUtil.generatePalette(bitmap),
+ defaultFooterColor()
+ )
+ )
+ deleteAlbumArt = false
}
override fun searchImageOnWeb() {
+ searchWebFor(binding.songText.text.toString(), binding.artistText.text.toString())
}
override fun deleteImage() {
+ setImageBitmap(
+ BitmapFactory.decodeResource(resources, R.drawable.default_audio_art),
+ defaultFooterColor()
+ )
+ deleteAlbumArt = true
+ dataChanged()
+ }
+
+ override fun setColors(color: Int) {
+ super.setColors(color)
+ saveFab.backgroundTintList = ColorStateList.valueOf(color)
+ ColorStateList.valueOf(
+ MaterialValueHelper.getPrimaryTextColor(
+ this,
+ color.isColorLight
+ )
+ ).also {
+ saveFab.iconTint = it
+ saveFab.setTextColor(it)
+ }
}
override fun save() {
val fieldKeyValueMap = EnumMap(FieldKey::class.java)
- fieldKeyValueMap[FieldKey.TITLE] = songText.text.toString()
- fieldKeyValueMap[FieldKey.ALBUM] = albumText.text.toString()
- fieldKeyValueMap[FieldKey.ARTIST] = artistText.text.toString()
- fieldKeyValueMap[FieldKey.GENRE] = genreText.text.toString()
- fieldKeyValueMap[FieldKey.YEAR] = yearText.text.toString()
- fieldKeyValueMap[FieldKey.TRACK] = trackNumberText.text.toString()
- fieldKeyValueMap[FieldKey.LYRICS] = lyricsText.text.toString()
- fieldKeyValueMap[FieldKey.ALBUM_ARTIST] = albumArtistText.text.toString()
- fieldKeyValueMap[FieldKey.COMPOSER] = songComposerText.text.toString()
- writeValuesToFiles(fieldKeyValueMap, null)
+ fieldKeyValueMap[FieldKey.TITLE] = binding.songText.text.toString()
+ fieldKeyValueMap[FieldKey.ALBUM] = binding.albumText.text.toString()
+ fieldKeyValueMap[FieldKey.ARTIST] = binding.artistText.text.toString()
+ fieldKeyValueMap[FieldKey.GENRE] = binding.genreText.text.toString()
+ fieldKeyValueMap[FieldKey.YEAR] = binding.yearText.text.toString()
+ fieldKeyValueMap[FieldKey.TRACK] = binding.trackNumberText.text.toString()
+ fieldKeyValueMap[FieldKey.DISC_NO] = binding.discNumberText.text.toString()
+ fieldKeyValueMap[FieldKey.LYRICS] = binding.lyricsText.text.toString()
+ fieldKeyValueMap[FieldKey.ALBUM_ARTIST] = binding.albumArtistText.text.toString()
+ fieldKeyValueMap[FieldKey.COMPOSER] = binding.songComposerText.text.toString()
+ writeValuesToFiles(
+ fieldKeyValueMap, when {
+ deleteAlbumArt -> ArtworkInfo(id, null)
+ albumArtBitmap == null -> null
+ else -> ArtworkInfo(id, albumArtBitmap!!)
+ }
+ )
}
- override fun getSongPaths(): List {
- val paths = ArrayList(1)
- paths.add(SongLoader.getSong(this, id).data)
- return paths
- }
+ override fun getSongPaths(): List = listOf(songRepository.song(id).data)
+
+ override fun getSongUris(): List = listOf(MusicUtil.getSongFileUri(id))
override fun loadImageFromFile(selectedFile: Uri?) {
- }
+ Glide.with(this@SongTagEditorActivity)
+ .asBitmapPalette()
+ .load(selectedFile)
+ .diskCacheStrategy(DiskCacheStrategy.NONE)
+ .skipMemoryCache(true)
+ .into(object : ImageViewTarget(binding.editorImage) {
+ override fun onResourceReady(
+ resource: BitmapPaletteWrapper,
+ transition: Transition?
+ ) {
+ RetroColorUtil.getColor(resource.palette, Color.TRANSPARENT)
+ albumArtBitmap = resource.bitmap?.let { ImageUtil.resizeBitmap(it, 2048) }
+ setImageBitmap(
+ albumArtBitmap,
+ RetroColorUtil.getColor(
+ resource.palette,
+ defaultFooterColor()
+ )
+ )
+ deleteAlbumArt = false
+ dataChanged()
+ setResult(Activity.RESULT_OK)
+ }
- override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
- }
+ override fun onLoadFailed(errorDrawable: Drawable?) {
+ super.onLoadFailed(errorDrawable)
+ showToast(R.string.error_load_failed, Toast.LENGTH_LONG)
+ }
- override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
- }
-
- override fun afterTextChanged(s: Editable) {
- dataChanged()
+ override fun setResource(resource: BitmapPaletteWrapper?) {}
+ })
}
companion object {
val TAG: String = SongTagEditorActivity::class.java.simpleName
}
+
+ override val editorImage: ImageView
+ get() = binding.editorImage
}
-
-
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/TagWriter.kt b/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/TagWriter.kt
new file mode 100644
index 000000000..b9d5f28dd
--- /dev/null
+++ b/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/TagWriter.kt
@@ -0,0 +1,204 @@
+package code.name.monkey.retromusic.activities.tageditor
+
+import android.app.Activity
+import android.content.Context
+import android.graphics.Bitmap
+import android.media.MediaScannerConnection
+import android.os.Build
+import android.util.Log
+import androidx.annotation.RequiresApi
+import code.name.monkey.retromusic.R
+import code.name.monkey.retromusic.extensions.showToast
+import code.name.monkey.retromusic.misc.UpdateToastMediaScannerCompletionListener
+import code.name.monkey.retromusic.model.AudioTagInfo
+import code.name.monkey.retromusic.util.MusicUtil.createAlbumArtFile
+import code.name.monkey.retromusic.util.MusicUtil.deleteAlbumArt
+import code.name.monkey.retromusic.util.MusicUtil.insertAlbumArt
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
+import org.jaudiotagger.audio.AudioFileIO
+import org.jaudiotagger.audio.exceptions.CannotReadException
+import org.jaudiotagger.audio.exceptions.CannotWriteException
+import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException
+import org.jaudiotagger.audio.exceptions.ReadOnlyFileException
+import org.jaudiotagger.tag.FieldDataInvalidException
+import org.jaudiotagger.tag.TagException
+import org.jaudiotagger.tag.images.AndroidArtwork
+import org.jaudiotagger.tag.images.Artwork
+import java.io.File
+import java.io.IOException
+
+class TagWriter {
+
+ companion object {
+
+ suspend fun scan(context: Context, toBeScanned: List?) {
+ if (toBeScanned.isNullOrEmpty()) {
+ Log.i("scan", "scan: Empty")
+ context.showToast("Scan file from folder")
+ return
+ }
+ MediaScannerConnection.scanFile(
+ context,
+ toBeScanned.toTypedArray(),
+ null,
+ withContext(Dispatchers.Main) {
+ if (context is Activity) UpdateToastMediaScannerCompletionListener(
+ context, toBeScanned
+ ) else null
+ }
+ )
+ }
+
+ suspend fun writeTagsToFiles(context: Context, info: AudioTagInfo) {
+ withContext(Dispatchers.IO) {
+ var artwork: Artwork? = null
+ var albumArtFile: File? = null
+ if (info.artworkInfo?.artwork != null) {
+ try {
+ albumArtFile = createAlbumArtFile(context).canonicalFile
+ info.artworkInfo.artwork.compress(
+ Bitmap.CompressFormat.JPEG,
+ 100,
+ albumArtFile.outputStream()
+ )
+ artwork = AndroidArtwork.createArtworkFromFile(albumArtFile)
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }
+ var wroteArtwork = false
+ var deletedArtwork = false
+ for (filePath in info.filePaths!!) {
+ try {
+ val audioFile = AudioFileIO.read(File(filePath))
+ val tag = audioFile.tagOrCreateAndSetDefault
+ if (info.fieldKeyValueMap != null) {
+ for ((key, value) in info.fieldKeyValueMap) {
+ try {
+ tag.setField(key, value)
+ } catch (e: FieldDataInvalidException) {
+ withContext(Dispatchers.Main) {
+ context.showToast(R.string.could_not_write_tags_to_file)
+ }
+ return@withContext listOf()
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ }
+ }
+ if (info.artworkInfo != null) {
+ if (info.artworkInfo.artwork == null) {
+ tag.deleteArtworkField()
+ deletedArtwork = true
+ } else if (artwork != null) {
+ tag.deleteArtworkField()
+ tag.setField(artwork)
+ wroteArtwork = true
+ }
+ }
+ audioFile.commit()
+ } catch (e: CannotReadException) {
+ e.printStackTrace()
+ } catch (e: IOException) {
+ e.printStackTrace()
+ } catch (e: CannotWriteException) {
+ e.printStackTrace()
+ } catch (e: TagException) {
+ e.printStackTrace()
+ } catch (e: ReadOnlyFileException) {
+ e.printStackTrace()
+ } catch (e: InvalidAudioFrameException) {
+ e.printStackTrace()
+ }
+ }
+ if (wroteArtwork) {
+ insertAlbumArt(context, info.artworkInfo!!.albumId, albumArtFile!!.path)
+ } else if (deletedArtwork) {
+ deleteAlbumArt(context, info.artworkInfo!!.albumId)
+ }
+ scan(context, info.filePaths)
+ }
+ }
+
+ @RequiresApi(Build.VERSION_CODES.R)
+ suspend fun writeTagsToFilesR(context: Context, info: AudioTagInfo): List =
+ withContext(Dispatchers.IO) {
+ val cacheFiles = mutableListOf()
+ var artwork: Artwork? = null
+ var albumArtFile: File? = null
+ if (info.artworkInfo?.artwork != null) {
+ try {
+ albumArtFile = createAlbumArtFile(context).canonicalFile
+ info.artworkInfo.artwork.compress(
+ Bitmap.CompressFormat.JPEG,
+ 100,
+ albumArtFile.outputStream()
+ )
+ artwork = AndroidArtwork.createArtworkFromFile(albumArtFile)
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }
+ var wroteArtwork = false
+ var deletedArtwork = false
+ for (filePath in info.filePaths!!) {
+ try {
+ val originFile = File(filePath)
+ val cacheFile = File(context.cacheDir, originFile.name)
+ cacheFiles.add(cacheFile)
+ originFile.inputStream().use { input ->
+ cacheFile.outputStream().use { output ->
+ input.copyTo(output)
+ }
+ }
+ val audioFile = AudioFileIO.read(cacheFile)
+ val tag = audioFile.tagOrCreateAndSetDefault
+ if (info.fieldKeyValueMap != null) {
+ for ((key, value) in info.fieldKeyValueMap) {
+ try {
+ tag.setField(key, value)
+ } catch (e: FieldDataInvalidException) {
+ withContext(Dispatchers.Main) {
+ context.showToast(R.string.could_not_write_tags_to_file)
+ }
+ return@withContext listOf()
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ }
+ }
+ if (info.artworkInfo != null) {
+ if (info.artworkInfo.artwork == null) {
+ tag.deleteArtworkField()
+ deletedArtwork = true
+ } else if (artwork != null) {
+ tag.deleteArtworkField()
+ tag.setField(artwork)
+ wroteArtwork = true
+ }
+ }
+ audioFile.commit()
+ } catch (e: CannotReadException) {
+ e.printStackTrace()
+ } catch (e: IOException) {
+ e.printStackTrace()
+ } catch (e: CannotWriteException) {
+ e.printStackTrace()
+ } catch (e: TagException) {
+ e.printStackTrace()
+ } catch (e: ReadOnlyFileException) {
+ e.printStackTrace()
+ } catch (e: InvalidAudioFrameException) {
+ e.printStackTrace()
+ }
+ }
+ if (wroteArtwork) {
+ insertAlbumArt(context, info.artworkInfo!!.albumId, albumArtFile!!.path)
+ } else if (deletedArtwork) {
+ deleteAlbumArt(context, info.artworkInfo!!.albumId)
+ }
+ cacheFiles
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/WriteTagsAsyncTask.java b/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/WriteTagsAsyncTask.java
deleted file mode 100644
index 81a8a7a59..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/WriteTagsAsyncTask.java
+++ /dev/null
@@ -1,193 +0,0 @@
-package code.name.monkey.retromusic.activities.tageditor;
-
-import android.app.Activity;
-import android.app.Dialog;
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.media.MediaScannerConnection;
-import android.net.Uri;
-import android.os.Build;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.google.android.material.dialog.MaterialAlertDialogBuilder;
-
-import org.jaudiotagger.audio.AudioFile;
-import org.jaudiotagger.audio.AudioFileIO;
-import org.jaudiotagger.tag.FieldKey;
-import org.jaudiotagger.tag.Tag;
-import org.jaudiotagger.tag.images.Artwork;
-import org.jaudiotagger.tag.images.ArtworkFactory;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Map;
-
-import code.name.monkey.retromusic.R;
-import code.name.monkey.retromusic.misc.DialogAsyncTask;
-import code.name.monkey.retromusic.misc.UpdateToastMediaScannerCompletionListener;
-import code.name.monkey.retromusic.util.MusicUtil;
-import code.name.monkey.retromusic.util.SAFUtil;
-
-public class WriteTagsAsyncTask extends
- DialogAsyncTask {
-
- private WeakReference activity;
-
- public WriteTagsAsyncTask(@NonNull Activity activity) {
- super(activity);
- this.activity = new WeakReference<>(activity);
- }
-
- @NonNull
- @Override
- protected Dialog createDialog(@NonNull Context context) {
-
- return new MaterialAlertDialogBuilder(context)
- .setTitle(R.string.saving_changes)
- .setCancelable(false)
- .setView(R.layout.loading)
- .create();
- }
-
- @Override
- protected String[] doInBackground(LoadingInfo... params) {
- try {
- LoadingInfo info = params[0];
-
- Artwork artwork = null;
- File albumArtFile = null;
- if (info.artworkInfo != null && info.artworkInfo.getArtwork() != null) {
- try {
- albumArtFile = MusicUtil.createAlbumArtFile().getCanonicalFile();
- info.artworkInfo.getArtwork()
- .compress(Bitmap.CompressFormat.PNG, 0, new FileOutputStream(albumArtFile));
- artwork = ArtworkFactory.createArtworkFromFile(albumArtFile);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- int counter = 0;
- boolean wroteArtwork = false;
- boolean deletedArtwork = false;
- for (String filePath : info.filePaths) {
- publishProgress(++counter, info.filePaths.size());
- try {
- Uri safUri = null;
- if (filePath.contains(SAFUtil.SEPARATOR)) {
- String[] fragments = filePath.split(SAFUtil.SEPARATOR);
- filePath = fragments[0];
- safUri = Uri.parse(fragments[1]);
- }
-
- AudioFile audioFile = AudioFileIO.read(new File(filePath));
- Tag tag = audioFile.getTagOrCreateAndSetDefault();
-
- if (info.fieldKeyValueMap != null) {
- for (Map.Entry entry : info.fieldKeyValueMap.entrySet()) {
- try {
- tag.setField(entry.getKey(), entry.getValue());
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
-
- if (info.artworkInfo != null) {
- if (info.artworkInfo.getArtwork() == null) {
- tag.deleteArtworkField();
- deletedArtwork = true;
- } else if (artwork != null) {
- tag.deleteArtworkField();
- tag.setField(artwork);
- wroteArtwork = true;
- }
- }
-
- Activity activity = this.activity.get();
- SAFUtil.write(activity, audioFile, safUri);
-
- } catch (@NonNull Exception e) {
- e.printStackTrace();
- }
- }
-
- Context context = getContext();
- if (context != null) {
- if (wroteArtwork) {
- MusicUtil.insertAlbumArt(context, info.artworkInfo.getAlbumId(), albumArtFile.getPath());
- } else if (deletedArtwork) {
- MusicUtil.deleteAlbumArt(context, info.artworkInfo.getAlbumId());
- }
- }
-
- Collection paths = info.filePaths;
- if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
- paths = new ArrayList<>(info.filePaths.size());
- for (String path : info.filePaths) {
- if (path.contains(SAFUtil.SEPARATOR)) {
- path = path.split(SAFUtil.SEPARATOR)[0];
- }
- paths.add(path);
- }
- }
-
- return paths.toArray(new String[paths.size()]);
- } catch (Exception e) {
- e.printStackTrace();
- return null;
- }
- }
-
- @Override
- protected void onCancelled(String[] toBeScanned) {
- super.onCancelled(toBeScanned);
- scan(toBeScanned);
- }
-
- @Override
- protected void onPostExecute(String[] toBeScanned) {
- super.onPostExecute(toBeScanned);
- scan(toBeScanned);
- }
-
- @Override
- protected void onProgressUpdate(@NonNull Dialog dialog, Integer... values) {
- super.onProgressUpdate(dialog, values);
- //((MaterialDialog) dialog).setMaxProgress(values[1]);
- //((MaterialDialog) dialog).setProgress(values[0]);
- }
-
- private void scan(String[] toBeScanned) {
- Activity activity = this.activity.get();
- if (activity != null) {
- MediaScannerConnection.scanFile(activity, toBeScanned, null,
- new UpdateToastMediaScannerCompletionListener(activity, toBeScanned));
- }
- }
-
- public static class LoadingInfo {
-
- @Nullable
- final Map fieldKeyValueMap;
-
- final Collection filePaths;
-
- @Nullable
- private AbsTagEditorActivity.ArtworkInfo artworkInfo;
-
- public LoadingInfo(Collection filePaths,
- @Nullable Map fieldKeyValueMap,
- @Nullable AbsTagEditorActivity.ArtworkInfo artworkInfo) {
- this.filePaths = filePaths;
- this.fieldKeyValueMap = fieldKeyValueMap;
- this.artworkInfo = artworkInfo;
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/CategoryInfoAdapter.java b/app/src/main/java/code/name/monkey/retromusic/adapter/CategoryInfoAdapter.java
deleted file mode 100644
index 58d6ce759..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/adapter/CategoryInfoAdapter.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (c) 2019 Hemanth Savarala.
- *
- * Licensed under the GNU General Public License v3
- *
- * This is free software: you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by
- * the Free Software Foundation either version 3 of the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- */
-
-package code.name.monkey.retromusic.adapter;
-
-import android.annotation.SuppressLint;
-import android.content.res.ColorStateList;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import androidx.annotation.NonNull;
-import androidx.recyclerview.widget.ItemTouchHelper;
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.google.android.material.checkbox.MaterialCheckBox;
-
-import java.util.List;
-
-import code.name.monkey.appthemehelper.ThemeStore;
-import code.name.monkey.retromusic.R;
-import code.name.monkey.retromusic.model.CategoryInfo;
-import code.name.monkey.retromusic.util.SwipeAndDragHelper;
-
-public class CategoryInfoAdapter extends RecyclerView.Adapter
- implements SwipeAndDragHelper.ActionCompletionContract {
-
- private List categoryInfos;
- private ItemTouchHelper touchHelper;
-
- public CategoryInfoAdapter() {
- SwipeAndDragHelper swipeAndDragHelper = new SwipeAndDragHelper(this);
- touchHelper = new ItemTouchHelper(swipeAndDragHelper);
- }
-
- public void attachToRecyclerView(RecyclerView recyclerView) {
- touchHelper.attachToRecyclerView(recyclerView);
- }
-
- @NonNull
- public List getCategoryInfos() {
- return categoryInfos;
- }
-
- public void setCategoryInfos(@NonNull List categoryInfos) {
- this.categoryInfos = categoryInfos;
- notifyDataSetChanged();
- }
-
- @Override
- public int getItemCount() {
- return categoryInfos.size();
- }
-
- @SuppressLint("ClickableViewAccessibility")
- @Override
- public void onBindViewHolder(@NonNull CategoryInfoAdapter.ViewHolder holder, int position) {
- CategoryInfo categoryInfo = categoryInfos.get(position);
-
- holder.checkBox.setChecked(categoryInfo.visible);
- holder.title.setText(holder.title.getResources().getString(categoryInfo.category.stringRes));
-
- holder.itemView.setOnClickListener(v -> {
- if (!(categoryInfo.visible && isLastCheckedCategory(categoryInfo))) {
- categoryInfo.visible = !categoryInfo.visible;
- holder.checkBox.setChecked(categoryInfo.visible);
- } else {
- Toast.makeText(holder.itemView.getContext(), R.string.you_have_to_select_at_least_one_category,
- Toast.LENGTH_SHORT).show();
- }
- });
-
- holder.dragView.setOnTouchListener((view, event) -> {
- if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
- touchHelper.startDrag(holder);
- }
- return false;
- }
- );
- }
-
- @Override
- @NonNull
- public CategoryInfoAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
- View view = LayoutInflater.from(parent.getContext())
- .inflate(R.layout.preference_dialog_library_categories_listitem, parent, false);
- return new ViewHolder(view);
- }
-
- @Override
- public void onViewMoved(int oldPosition, int newPosition) {
- CategoryInfo categoryInfo = categoryInfos.get(oldPosition);
- categoryInfos.remove(oldPosition);
- categoryInfos.add(newPosition, categoryInfo);
- notifyItemMoved(oldPosition, newPosition);
- }
-
- private boolean isLastCheckedCategory(CategoryInfo categoryInfo) {
- if (categoryInfo.visible) {
- for (CategoryInfo c : categoryInfos) {
- if (c != categoryInfo && c.visible) {
- return false;
- }
- }
- }
- return true;
- }
-
- static class ViewHolder extends RecyclerView.ViewHolder {
- private MaterialCheckBox checkBox;
- private View dragView;
- private TextView title;
-
- ViewHolder(View view) {
- super(view);
- checkBox = view.findViewById(R.id.checkbox);
- checkBox.setButtonTintList(
- ColorStateList.valueOf(ThemeStore.Companion.accentColor(checkBox.getContext())));
- title = view.findViewById(R.id.title);
- dragView = view.findViewById(R.id.drag_view);
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/CategoryInfoAdapter.kt b/app/src/main/java/code/name/monkey/retromusic/adapter/CategoryInfoAdapter.kt
new file mode 100644
index 000000000..dd5cda1d3
--- /dev/null
+++ b/app/src/main/java/code/name/monkey/retromusic/adapter/CategoryInfoAdapter.kt
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2019 Hemanth Savarala.
+ *
+ * Licensed under the GNU General Public License v3
+ *
+ * This is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by
+ * the Free Software Foundation either version 3 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ */
+package code.name.monkey.retromusic.adapter
+
+import android.annotation.SuppressLint
+import android.content.res.ColorStateList
+import android.view.LayoutInflater
+import android.view.MotionEvent
+import android.view.View
+import android.view.ViewGroup
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.RecyclerView
+import code.name.monkey.appthemehelper.ThemeStore.Companion.accentColor
+import code.name.monkey.retromusic.R
+import code.name.monkey.retromusic.databinding.PreferenceDialogLibraryCategoriesListitemBinding
+import code.name.monkey.retromusic.extensions.showToast
+import code.name.monkey.retromusic.model.CategoryInfo
+import code.name.monkey.retromusic.util.PreferenceUtil
+import code.name.monkey.retromusic.util.SwipeAndDragHelper
+import code.name.monkey.retromusic.util.SwipeAndDragHelper.ActionCompletionContract
+
+class CategoryInfoAdapter : RecyclerView.Adapter(),
+ ActionCompletionContract {
+ var categoryInfos: MutableList =
+ PreferenceUtil.libraryCategory.toMutableList()
+ @SuppressLint("NotifyDataSetChanged")
+ set(value) {
+ field = value
+ notifyDataSetChanged()
+ }
+ private val touchHelper: ItemTouchHelper
+ fun attachToRecyclerView(recyclerView: RecyclerView?) {
+ touchHelper.attachToRecyclerView(recyclerView)
+ }
+
+ override fun getItemCount(): Int {
+ return categoryInfos.size
+ }
+
+ @SuppressLint("ClickableViewAccessibility")
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ val categoryInfo = categoryInfos[position]
+ holder.binding.checkbox.isChecked = categoryInfo.visible
+ holder.binding.title.text =
+ holder.binding.title.resources.getString(categoryInfo.category.stringRes)
+ holder.itemView.setOnClickListener {
+ if (!(categoryInfo.visible && isLastCheckedCategory(categoryInfo))) {
+ categoryInfo.visible = !categoryInfo.visible
+ holder.binding.checkbox.isChecked = categoryInfo.visible
+ } else {
+ holder.itemView.context.showToast(R.string.you_have_to_select_at_least_one_category)
+ }
+ }
+ holder.binding.dragView.setOnTouchListener { _: View?, event: MotionEvent ->
+ if (event.actionMasked == MotionEvent.ACTION_DOWN) {
+ touchHelper.startDrag(holder)
+ }
+ false
+ }
+ }
+
+ override fun onCreateViewHolder(
+ parent: ViewGroup, viewType: Int
+ ): ViewHolder {
+ return ViewHolder(
+ PreferenceDialogLibraryCategoriesListitemBinding.inflate(
+ LayoutInflater.from(
+ parent.context
+ ), parent, false
+ )
+ )
+ }
+
+ override fun onViewMoved(oldPosition: Int, newPosition: Int) {
+ val categoryInfo = categoryInfos[oldPosition]
+ categoryInfos.removeAt(oldPosition)
+ categoryInfos.add(newPosition, categoryInfo)
+ notifyItemMoved(oldPosition, newPosition)
+ }
+
+ private fun isLastCheckedCategory(categoryInfo: CategoryInfo): Boolean {
+ if (categoryInfo.visible) {
+ for (c in categoryInfos) {
+ if (c !== categoryInfo && c.visible) {
+ return false
+ }
+ }
+ }
+ return true
+ }
+
+ class ViewHolder(val binding: PreferenceDialogLibraryCategoriesListitemBinding) :
+ RecyclerView.ViewHolder(binding.root) {
+
+ init {
+ binding.checkbox.buttonTintList =
+ ColorStateList.valueOf(accentColor(binding.checkbox.context))
+ }
+ }
+
+ init {
+ val swipeAndDragHelper = SwipeAndDragHelper(this)
+ touchHelper = ItemTouchHelper(swipeAndDragHelper)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/ContributorAdapter.kt b/app/src/main/java/code/name/monkey/retromusic/adapter/ContributorAdapter.kt
deleted file mode 100644
index dcd0f7bd0..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/adapter/ContributorAdapter.kt
+++ /dev/null
@@ -1,78 +0,0 @@
-package code.name.monkey.retromusic.adapter
-
-import android.app.Activity
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.TextView
-import androidx.recyclerview.widget.RecyclerView
-import code.name.monkey.retromusic.R
-import code.name.monkey.retromusic.model.Contributor
-import code.name.monkey.retromusic.util.RetroUtil.openUrl
-import code.name.monkey.retromusic.views.RetroShapeableImageView
-import com.bumptech.glide.Glide
-
-class ContributorAdapter(
- private var contributors: List
-) : RecyclerView.Adapter() {
-
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
- return if (viewType == HEADER) {
- ViewHolder(
- LayoutInflater.from(parent.context).inflate(
- R.layout.item_contributor_header,
- parent,
- false
- )
- )
- } else ViewHolder(
- LayoutInflater.from(parent.context).inflate(
- R.layout.item_contributor,
- parent,
- false
- )
- )
- }
-
- companion object {
- const val HEADER: Int = 0
- const val ITEM: Int = 1
- }
-
- override fun getItemViewType(position: Int): Int {
- return if (position == 0) {
- HEADER
- } else {
- ITEM
- }
- }
-
- override fun onBindViewHolder(holder: ViewHolder, position: Int) {
- val contributor = contributors[position]
- holder.bindData(contributor)
- holder.itemView.setOnClickListener {
- openUrl(it?.context as Activity, contributors[position].link)
- }
- }
-
- override fun getItemCount(): Int {
- return contributors.size
- }
-
- inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
- val title: TextView = itemView.findViewById(R.id.title)
- val text: TextView = itemView.findViewById(R.id.text)
- val image: RetroShapeableImageView = itemView.findViewById(R.id.icon)
-
- internal fun bindData(contributor: Contributor) {
- title.text = contributor.name
- text.text = contributor.summary
- Glide.with(image.context)
- .load(contributor.profileImage)
- .error(R.drawable.ic_account_white_24dp)
- .placeholder(R.drawable.ic_account_white_24dp)
- .dontAnimate()
- .into(image)
- }
- }
-}
diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/GenreAdapter.kt b/app/src/main/java/code/name/monkey/retromusic/adapter/GenreAdapter.kt
index 570912a30..b139a0af8 100644
--- a/app/src/main/java/code/name/monkey/retromusic/adapter/GenreAdapter.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/adapter/GenreAdapter.kt
@@ -1,14 +1,37 @@
+/*
+ * Copyright (c) 2020 Hemanth Savarla.
+ *
+ * Licensed under the GNU General Public License v3
+ *
+ * This is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ */
package code.name.monkey.retromusic.adapter
-import android.app.Activity
+import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.view.ViewOutlineProvider
+import androidx.fragment.app.FragmentActivity
import androidx.recyclerview.widget.RecyclerView
import code.name.monkey.retromusic.R
-import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder
+import code.name.monkey.retromusic.databinding.ItemGenreBinding
+import code.name.monkey.retromusic.glide.RetroGlideExtension
+import code.name.monkey.retromusic.glide.RetroGlideExtension.asBitmapPalette
+import code.name.monkey.retromusic.glide.RetroGlideExtension.songCoverOptions
+import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
+import code.name.monkey.retromusic.interfaces.IGenreClickListener
import code.name.monkey.retromusic.model.Genre
-import code.name.monkey.retromusic.util.NavigationUtil
+import code.name.monkey.retromusic.util.MusicUtil
+import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
+import com.bumptech.glide.Glide
import java.util.*
/**
@@ -16,41 +39,74 @@ import java.util.*
*/
class GenreAdapter(
- private val activity: Activity,
+ private val activity: FragmentActivity,
var dataSet: List,
- private val mItemLayoutRes: Int
+ private val listener: IGenreClickListener
) : RecyclerView.Adapter() {
+ init {
+ this.setHasStableIds(true)
+ }
+
+ override fun getItemId(position: Int): Long {
+ return dataSet[position].id
+ }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
- return ViewHolder(LayoutInflater.from(activity).inflate(mItemLayoutRes, parent, false))
+ return ViewHolder(ItemGenreBinding.inflate(LayoutInflater.from(activity), parent, false))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val genre = dataSet[position]
- holder.title?.text = genre.name
- holder.text?.text = String.format(
+ holder.binding.title.text = genre.name
+ holder.binding.text.text = String.format(
Locale.getDefault(),
"%d %s",
genre.songCount,
if (genre.songCount > 1) activity.getString(R.string.songs) else activity.getString(R.string.song)
)
+ loadGenreImage(genre, holder)
+ }
+
+ private fun loadGenreImage(genre: Genre, holder: GenreAdapter.ViewHolder) {
+ val genreSong = MusicUtil.songByGenre(genre.id)
+ Glide.with(activity)
+ .asBitmapPalette()
+ .songCoverOptions(genreSong)
+ .load(RetroGlideExtension.getSongModel(genreSong))
+ .into(object : RetroMusicColoredTarget(holder.binding.image) {
+ override fun onColorReady(colors: MediaNotificationProcessor) {
+ setColors(holder, colors)
+ }
+ })
+ // Just for a bit of shadow around image
+ holder.binding.image.outlineProvider = ViewOutlineProvider.BOUNDS
+ }
+
+ private fun setColors(holder: ViewHolder, color: MediaNotificationProcessor) {
+ holder.binding.imageContainerCard.setCardBackgroundColor(color.backgroundColor)
+ holder.binding.title.setTextColor(color.primaryTextColor)
+ holder.binding.text.setTextColor(color.secondaryTextColor)
}
override fun getItemCount(): Int {
return dataSet.size
}
+ @SuppressLint("NotifyDataSetChanged")
fun swapDataSet(list: List) {
dataSet = list
notifyDataSetChanged()
}
- inner class ViewHolder(itemView: View) : MediaEntryViewHolder(itemView) {
+ inner class ViewHolder(val binding: ItemGenreBinding) : RecyclerView.ViewHolder(binding.root),
+ View.OnClickListener {
override fun onClick(v: View?) {
- super.onClick(v)
- val genre = dataSet[layoutPosition]
- NavigationUtil.goToGenre(activity, genre)
+ listener.onClickGenre(dataSet[layoutPosition], itemView)
+ }
+
+ init {
+ itemView.setOnClickListener(this)
}
}
}
diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/HomeAdapter.kt b/app/src/main/java/code/name/monkey/retromusic/adapter/HomeAdapter.kt
index 0dcfb0a0d..e3f809b5f 100644
--- a/app/src/main/java/code/name/monkey/retromusic/adapter/HomeAdapter.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/adapter/HomeAdapter.kt
@@ -1,32 +1,47 @@
+/*
+ * Copyright (c) 2020 Hemanth Savarla.
+ *
+ * Licensed under the GNU General Public License v3
+ *
+ * This is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ */
package code.name.monkey.retromusic.adapter
-import android.util.DisplayMetrics
+import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import androidx.annotation.IntDef
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.AppCompatTextView
+import androidx.core.os.bundleOf
+import androidx.fragment.app.findFragment
+import androidx.navigation.findNavController
+import androidx.navigation.fragment.FragmentNavigatorExtras
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
-import code.name.monkey.retromusic.R
-import code.name.monkey.retromusic.adapter.album.AlbumFullWidthAdapter
+import code.name.monkey.retromusic.*
+import code.name.monkey.retromusic.adapter.album.AlbumAdapter
import code.name.monkey.retromusic.adapter.artist.ArtistAdapter
import code.name.monkey.retromusic.adapter.song.SongAdapter
-import code.name.monkey.retromusic.extensions.show
-import code.name.monkey.retromusic.loaders.PlaylistSongsLoader
+import code.name.monkey.retromusic.fragments.home.HomeFragment
+import code.name.monkey.retromusic.interfaces.IAlbumClickListener
+import code.name.monkey.retromusic.interfaces.IArtistClickListener
import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.model.Home
-import code.name.monkey.retromusic.model.Playlist
-
+import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.PreferenceUtil
-class HomeAdapter(
- private val activity: AppCompatActivity,
- private val displayMetrics: DisplayMetrics
-) : RecyclerView.Adapter() {
+class HomeAdapter(private val activity: AppCompatActivity) :
+ RecyclerView.Adapter(), IArtistClickListener, IAlbumClickListener {
private var list = listOf()
@@ -35,44 +50,75 @@ class HomeAdapter(
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
- val layout = LayoutInflater.from(activity)
- .inflate(R.layout.section_recycler_view, parent, false)
+ val layout =
+ LayoutInflater.from(activity).inflate(R.layout.section_recycler_view, parent, false)
return when (viewType) {
RECENT_ARTISTS, TOP_ARTISTS -> ArtistViewHolder(layout)
- PLAYLISTS -> PlaylistViewHolder(layout)
+ FAVOURITES -> PlaylistViewHolder(layout)
+ TOP_ALBUMS, RECENT_ALBUMS -> AlbumViewHolder(layout)
else -> {
- AlbumViewHolder(
- LayoutInflater.from(activity).inflate(
- R.layout.metal_section_recycler_view,
- parent,
- false
- )
- )
+ ArtistViewHolder(layout)
}
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
+ val home = list[position]
when (getItemViewType(position)) {
RECENT_ALBUMS -> {
val viewHolder = holder as AlbumViewHolder
- viewHolder.bindView(list[position].arrayList.toAlbums(), R.string.recent_albums)
+ viewHolder.bindView(home)
+ viewHolder.clickableArea.setOnClickListener {
+ it.findFragment().setSharedAxisXTransitions()
+ activity.findNavController(R.id.fragment_container).navigate(
+ R.id.detailListFragment,
+ bundleOf("type" to RECENT_ALBUMS)
+ )
+ }
}
TOP_ALBUMS -> {
val viewHolder = holder as AlbumViewHolder
- viewHolder.bindView(list[position].arrayList.toAlbums(), R.string.top_albums)
+ viewHolder.bindView(home)
+ viewHolder.clickableArea.setOnClickListener {
+ it.findFragment().setSharedAxisXTransitions()
+ activity.findNavController(R.id.fragment_container).navigate(
+ R.id.detailListFragment,
+ bundleOf("type" to TOP_ALBUMS)
+ )
+ }
}
RECENT_ARTISTS -> {
val viewHolder = holder as ArtistViewHolder
- viewHolder.bindView(list[position].arrayList.toArtists(), R.string.recent_artists)
+ viewHolder.bindView(home)
+ viewHolder.clickableArea.setOnClickListener {
+ it.findFragment().setSharedAxisXTransitions()
+ activity.findNavController(R.id.fragment_container).navigate(
+ R.id.detailListFragment,
+ bundleOf("type" to RECENT_ARTISTS)
+ )
+ }
}
TOP_ARTISTS -> {
val viewHolder = holder as ArtistViewHolder
- viewHolder.bindView(list[position].arrayList.toArtists(), R.string.top_artists)
+ viewHolder.bindView(home)
+ viewHolder.clickableArea.setOnClickListener {
+ it.findFragment().setSharedAxisXTransitions()
+ activity.findNavController(R.id.fragment_container).navigate(
+ R.id.detailListFragment,
+ bundleOf("type" to TOP_ARTISTS)
+ )
+ }
}
- PLAYLISTS -> {
+ FAVOURITES -> {
val viewHolder = holder as PlaylistViewHolder
- viewHolder.bindView(list[position].arrayList.toPlaylist(), R.string.favorites)
+ viewHolder.bindView(home)
+ viewHolder.clickableArea.setOnClickListener {
+ it.findFragment().setSharedAxisXTransitions()
+ activity.findNavController(R.id.fragment_container).navigate(
+ R.id.detailListFragment,
+ bundleOf("type" to FAVOURITES)
+ )
+ }
}
}
}
@@ -81,102 +127,87 @@ class HomeAdapter(
return list.size
}
+ @SuppressLint("NotifyDataSetChanged")
fun swapData(sections: List) {
list = sections
notifyDataSetChanged()
}
- companion object {
-
- @IntDef(RECENT_ALBUMS, TOP_ALBUMS, RECENT_ARTISTS, TOP_ARTISTS, PLAYLISTS)
- @Retention(AnnotationRetention.SOURCE)
- annotation class HomeSection
-
- const val RECENT_ALBUMS = 3
- const val TOP_ALBUMS = 1
- const val RECENT_ARTISTS = 2
- const val TOP_ARTISTS = 0
- const val PLAYLISTS = 4
- }
-
+ @Suppress("UNCHECKED_CAST")
private inner class AlbumViewHolder(view: View) : AbsHomeViewItem(view) {
- fun bindView(list: ArrayList, titleRes: Int) {
- if (list.isNotEmpty()) {
- recyclerView.apply {
- show()
- adapter = AlbumFullWidthAdapter(activity, list, displayMetrics)
- }
- title.text = activity.getString(titleRes)
+ fun bindView(home: Home) {
+ title.setText(home.titleRes)
+ recyclerView.apply {
+ adapter = albumAdapter(home.arrayList as List)
+ layoutManager = gridLayoutManager()
}
}
}
- inner class ArtistViewHolder(view: View) : AbsHomeViewItem(view) {
- fun bindView(list: ArrayList, titleRes: Int) {
- if (list.isNotEmpty()) {
- val manager = LinearLayoutManager(activity, LinearLayoutManager.HORIZONTAL, false)
- val artistAdapter = ArtistAdapter(
- activity,
- list,
- PreferenceUtil.homeGridStyle,
- null
- )
- recyclerView.apply {
- show()
- layoutManager = manager
- adapter = artistAdapter
- }
- title.text = activity.getString(titleRes)
+ @Suppress("UNCHECKED_CAST")
+ private inner class ArtistViewHolder(view: View) : AbsHomeViewItem(view) {
+ fun bindView(home: Home) {
+ title.setText(home.titleRes)
+ recyclerView.apply {
+ layoutManager = linearLayoutManager()
+ adapter = artistsAdapter(home.arrayList as List)
}
}
}
+ @Suppress("UNCHECKED_CAST")
private inner class PlaylistViewHolder(view: View) : AbsHomeViewItem(view) {
- fun bindView(arrayList: ArrayList, titleRes: Int) {
- if (arrayList.isNotEmpty()) {
- val songs = PlaylistSongsLoader.getPlaylistSongList(activity, arrayList[0])
- if (songs.isNotEmpty()) {
- recyclerView.apply {
- show()
- val songAdapter =
- SongAdapter(activity, songs, R.layout.item_album_card, null)
- layoutManager =
- GridLayoutManager(activity, 1, GridLayoutManager.HORIZONTAL, false)
- adapter = songAdapter
- }
- title.text = activity.getString(titleRes)
- }
+ fun bindView(home: Home) {
+ title.setText(home.titleRes)
+ recyclerView.apply {
+ val songAdapter = SongAdapter(
+ activity,
+ home.arrayList as MutableList,
+ R.layout.item_favourite_card
+ )
+ layoutManager = linearLayoutManager()
+ adapter = songAdapter
}
}
}
- open inner class AbsHomeViewItem(itemView: View) : RecyclerView.ViewHolder(itemView) {
+ open class AbsHomeViewItem(itemView: View) : RecyclerView.ViewHolder(itemView) {
val recyclerView: RecyclerView = itemView.findViewById(R.id.recyclerView)
val title: AppCompatTextView = itemView.findViewById(R.id.title)
+ val clickableArea: ViewGroup = itemView.findViewById(R.id.clickable_area)
+ }
+
+ private fun artistsAdapter(artists: List) =
+ ArtistAdapter(activity, artists, PreferenceUtil.homeArtistGridStyle, this)
+
+ private fun albumAdapter(albums: List) =
+ AlbumAdapter(activity, albums, PreferenceUtil.homeAlbumGridStyle, this)
+
+ private fun gridLayoutManager() =
+ GridLayoutManager(activity, 1, GridLayoutManager.HORIZONTAL, false)
+
+ private fun linearLayoutManager() =
+ LinearLayoutManager(activity, LinearLayoutManager.HORIZONTAL, false)
+
+ override fun onArtist(artistId: Long, view: View) {
+ activity.findNavController(R.id.fragment_container).navigate(
+ R.id.artistDetailsFragment,
+ bundleOf(EXTRA_ARTIST_ID to artistId),
+ null,
+ FragmentNavigatorExtras(
+ view to artistId.toString()
+ )
+ )
+ }
+
+ override fun onAlbumClick(albumId: Long, view: View) {
+ activity.findNavController(R.id.fragment_container).navigate(
+ R.id.albumDetailsFragment,
+ bundleOf(EXTRA_ALBUM_ID to albumId),
+ null,
+ FragmentNavigatorExtras(
+ view to albumId.toString()
+ )
+ )
}
}
-
-private fun ArrayList.toAlbums(): ArrayList {
- val arrayList = ArrayList()
- for (x in this) {
- arrayList.add(x as Album)
- }
- return arrayList
-}
-
-private fun ArrayList.toArtists(): ArrayList {
- val arrayList = ArrayList()
- for (x in this) {
- arrayList.add(x as Artist)
- }
- return arrayList
-}
-
-private fun ArrayList.toPlaylist(): ArrayList {
- val arrayList = ArrayList()
- for (x in this) {
- arrayList.add(x as Playlist)
- }
- return arrayList
-}
-
diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/SearchAdapter.kt b/app/src/main/java/code/name/monkey/retromusic/adapter/SearchAdapter.kt
index 0b257978d..22a60bd95 100644
--- a/app/src/main/java/code/name/monkey/retromusic/adapter/SearchAdapter.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/adapter/SearchAdapter.kt
@@ -1,122 +1,176 @@
+/*
+ * Copyright (c) 2020 Hemanth Savarla.
+ *
+ * Licensed under the GNU General Public License v3
+ *
+ * This is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ */
package code.name.monkey.retromusic.adapter
-import android.app.ActivityOptions
+import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import androidx.appcompat.app.AppCompatActivity
+import androidx.core.os.bundleOf
+import androidx.core.view.isGone
+import androidx.core.view.isInvisible
+import androidx.core.view.isVisible
+import androidx.fragment.app.FragmentActivity
+import androidx.navigation.findNavController
import androidx.recyclerview.widget.RecyclerView
import code.name.monkey.appthemehelper.ThemeStore
-import code.name.monkey.retromusic.R
+import code.name.monkey.retromusic.*
import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder
-import code.name.monkey.retromusic.glide.AlbumGlideRequest
-import code.name.monkey.retromusic.glide.ArtistGlideRequest
+import code.name.monkey.retromusic.db.PlaylistWithSongs
+import code.name.monkey.retromusic.glide.RetroGlideExtension
+import code.name.monkey.retromusic.glide.RetroGlideExtension.albumCoverOptions
+import code.name.monkey.retromusic.glide.RetroGlideExtension.artistImageOptions
+import code.name.monkey.retromusic.glide.RetroGlideExtension.songCoverOptions
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.menu.SongMenuHelper
-import code.name.monkey.retromusic.loaders.PlaylistSongsLoader
-import code.name.monkey.retromusic.model.*
-import code.name.monkey.retromusic.model.smartplaylist.AbsSmartPlaylist
+import code.name.monkey.retromusic.model.Album
+import code.name.monkey.retromusic.model.Artist
+import code.name.monkey.retromusic.model.Genre
+import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.MusicUtil
-import code.name.monkey.retromusic.util.NavigationUtil
import com.bumptech.glide.Glide
-import android.util.Pair as UtilPair
+import java.util.*
class SearchAdapter(
- private val activity: AppCompatActivity,
- private var dataSet: List?
+ private val activity: FragmentActivity,
+ private var dataSet: List
) : RecyclerView.Adapter() {
- fun swapDataSet(dataSet: MutableList) {
+ @SuppressLint("NotifyDataSetChanged")
+ fun swapDataSet(dataSet: List) {
this.dataSet = dataSet
notifyDataSetChanged()
}
override fun getItemViewType(position: Int): Int {
- if (dataSet!![position] is Album) return ALBUM
- if (dataSet!![position] is Artist) return ARTIST
- if (dataSet!![position] is Genre) return GENRE
- if (dataSet!![position] is Playlist) return PLAYLIST
- return if (dataSet!![position] is Song) SONG else HEADER
+ if (dataSet[position] is Album) return ALBUM
+ if (dataSet[position] is Artist) return if ((dataSet[position] as Artist).isAlbumArtist) ALBUM_ARTIST else ARTIST
+ if (dataSet[position] is Genre) return GENRE
+ if (dataSet[position] is PlaylistWithSongs) return PLAYLIST
+ return if (dataSet[position] is Song) SONG else HEADER
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
- return if (viewType == HEADER) ViewHolder(
- LayoutInflater.from(activity).inflate(
- R.layout.sub_header,
- parent,
- false
- ), viewType
- )
- else
- ViewHolder(
+ return when (viewType) {
+ HEADER -> ViewHolder(
+ LayoutInflater.from(activity).inflate(
+ R.layout.sub_header,
+ parent,
+ false
+ ), viewType
+ )
+
+ ALBUM, ARTIST, ALBUM_ARTIST -> ViewHolder(
+ LayoutInflater.from(activity).inflate(
+ R.layout.item_list_big,
+ parent,
+ false
+ ), viewType
+ )
+
+ else -> ViewHolder(
LayoutInflater.from(activity).inflate(R.layout.item_list, parent, false),
viewType
)
+ }
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
when (getItemViewType(position)) {
ALBUM -> {
- val album = dataSet?.get(position) as Album
+ holder.imageTextContainer?.isVisible = true
+ val album = dataSet[position] as Album
holder.title?.text = album.title
holder.text?.text = album.artistName
- AlbumGlideRequest.Builder.from(Glide.with(activity), album.safeGetFirstSong())
- .checkIgnoreMediaStore(activity).build().into(holder.image)
+ Glide.with(activity).asDrawable().albumCoverOptions(album.safeGetFirstSong())
+ .load(RetroGlideExtension.getSongModel(album.safeGetFirstSong()))
+ .into(holder.image!!)
}
+
ARTIST -> {
- val artist = dataSet?.get(position) as Artist
+ holder.imageTextContainer?.isVisible = true
+ val artist = dataSet[position] as Artist
holder.title?.text = artist.name
holder.text?.text = MusicUtil.getArtistInfoString(activity, artist)
- ArtistGlideRequest.Builder.from(Glide.with(activity), artist).build()
- .into(holder.image)
+ Glide.with(activity).asDrawable().artistImageOptions(artist).load(
+ RetroGlideExtension.getArtistModel(artist)
+ ).into(holder.image!!)
}
+
SONG -> {
- val song = dataSet?.get(position) as Song
+ holder.imageTextContainer?.isVisible = true
+ val song = dataSet[position] as Song
holder.title?.text = song.title
holder.text?.text = song.albumName
+ Glide.with(activity).asDrawable().songCoverOptions(song)
+ .load(RetroGlideExtension.getSongModel(song)).into(holder.image!!)
}
+
GENRE -> {
- val genre = dataSet?.get(position) as Genre
+ val genre = dataSet[position] as Genre
holder.title?.text = genre.name
+ holder.text?.text = String.format(
+ Locale.getDefault(),
+ "%d %s",
+ genre.songCount,
+ if (genre.songCount > 1) activity.getString(R.string.songs) else activity.getString(
+ R.string.song
+ )
+ )
}
+
PLAYLIST -> {
- val playlist = dataSet?.get(position) as Playlist
- holder.title?.text = playlist.name
- holder.text?.text = MusicUtil.getPlaylistInfoString(activity, getSongs(playlist))
+ val playlist = dataSet[position] as PlaylistWithSongs
+ holder.title?.text = playlist.playlistEntity.playlistName
+ //holder.text?.text = MusicUtil.playlistInfoString(activity, playlist.songs)
}
+
+ ALBUM_ARTIST -> {
+ holder.imageTextContainer?.isVisible = true
+ val artist = dataSet[position] as Artist
+ holder.title?.text = artist.name
+ holder.text?.text = MusicUtil.getArtistInfoString(activity, artist)
+ Glide.with(activity).asDrawable().artistImageOptions(artist).load(
+ RetroGlideExtension.getArtistModel(artist)
+ ).into(holder.image!!)
+ }
+
else -> {
- holder.title?.text = dataSet?.get(position).toString()
+ holder.title?.text = dataSet[position].toString()
holder.title?.setTextColor(ThemeStore.accentColor(activity))
}
}
}
- private fun getSongs(playlist: Playlist): java.util.ArrayList {
- val songs = java.util.ArrayList()
- if (playlist is AbsSmartPlaylist) {
- songs.addAll(playlist.getSongs(activity))
- } else {
- songs.addAll(PlaylistSongsLoader.getPlaylistSongList(activity, playlist.id))
- }
- return songs
- }
-
override fun getItemCount(): Int {
- return dataSet!!.size
+ return dataSet.size
}
inner class ViewHolder(itemView: View, itemViewType: Int) : MediaEntryViewHolder(itemView) {
init {
itemView.setOnLongClickListener(null)
-
+ imageTextContainer?.isInvisible = true
if (itemViewType == SONG) {
- menu?.visibility = View.VISIBLE
+ imageTextContainer?.isGone = true
+ menu?.isVisible = true
menu?.setOnClickListener(object : SongMenuHelper.OnClickSongMenu(activity) {
override val song: Song
- get() = dataSet!![layoutPosition] as Song
+ get() = dataSet[layoutPosition] as Song
})
} else {
- menu?.visibility = View.GONE
+ menu?.isVisible = false
}
when (itemViewType) {
@@ -124,38 +178,52 @@ class SearchAdapter(
ARTIST -> setImageTransitionName(activity.getString(R.string.transition_artist_image))
else -> {
val container = itemView.findViewById(R.id.imageContainer)
- container?.visibility = View.GONE
+ container?.isVisible = false
}
}
}
override fun onClick(v: View?) {
- val item = dataSet!![layoutPosition]
+ val item = dataSet[layoutPosition]
when (itemViewType) {
ALBUM -> {
- val options = ActivityOptions.makeSceneTransitionAnimation(
- activity,
- UtilPair.create(image, activity.getString(R.string.transition_album_art))
+ activity.findNavController(R.id.fragment_container).navigate(
+ R.id.albumDetailsFragment,
+ bundleOf(EXTRA_ALBUM_ID to (item as Album).id)
)
- NavigationUtil.goToAlbumOptions(activity, (item as Album).id, options)
}
+
ARTIST -> {
- val options = ActivityOptions.makeSceneTransitionAnimation(
- activity,
- UtilPair.create(image, activity.getString(R.string.transition_artist_image))
+ activity.findNavController(R.id.fragment_container).navigate(
+ R.id.artistDetailsFragment,
+ bundleOf(EXTRA_ARTIST_ID to (item as Artist).id)
)
- NavigationUtil.goToArtistOptions(activity, (item as Artist).id, options)
}
+
+ ALBUM_ARTIST -> {
+ activity.findNavController(R.id.fragment_container).navigate(
+ R.id.albumArtistDetailsFragment,
+ bundleOf(EXTRA_ARTIST_NAME to (item as Artist).name)
+ )
+ }
+
GENRE -> {
- NavigationUtil.goToGenre(activity, item as Genre)
+ activity.findNavController(R.id.fragment_container).navigate(
+ R.id.genreDetailsFragment,
+ bundleOf(EXTRA_GENRE to (item as Genre))
+ )
}
+
PLAYLIST -> {
- NavigationUtil.goToPlaylistNew(activity, item as Playlist)
+ activity.findNavController(R.id.fragment_container).navigate(
+ R.id.playlistDetailsFragment,
+ bundleOf(EXTRA_PLAYLIST_ID to (item as PlaylistWithSongs).playlistEntity.playListId)
+ )
}
+
SONG -> {
- val playList = ArrayList()
- playList.add(item as Song)
- MusicPlayerRemote.openQueue(playList, 0, true)
+ MusicPlayerRemote.playNext(item as Song)
+ MusicPlayerRemote.playNextSong()
}
}
}
@@ -168,5 +236,6 @@ class SearchAdapter(
private const val SONG = 3
private const val GENRE = 4
private const val PLAYLIST = 5
+ private const val ALBUM_ARTIST = 6
}
}
diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/SongFileAdapter.kt b/app/src/main/java/code/name/monkey/retromusic/adapter/SongFileAdapter.kt
index daaba32dc..4005c6e6c 100644
--- a/app/src/main/java/code/name/monkey/retromusic/adapter/SongFileAdapter.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/adapter/SongFileAdapter.kt
@@ -1,17 +1,16 @@
/*
- * Copyright 2019 Google LLC
+ * Copyright (c) 2020 Hemanth Savarla.
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed under the GNU General Public License v3
*
- * https://www.apache.org/licenses/LICENSE-2.0
+ * This is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
*/
package code.name.monkey.retromusic.adapter
@@ -21,32 +20,31 @@ import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
+import androidx.core.view.isVisible
import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.base.AbsMultiSelectAdapter
-import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder
+import code.name.monkey.retromusic.extensions.getTintedDrawable
+import code.name.monkey.retromusic.glide.RetroGlideExtension
import code.name.monkey.retromusic.glide.audiocover.AudioFileCover
-import code.name.monkey.retromusic.interfaces.CabHolder
+import code.name.monkey.retromusic.interfaces.ICallbacks
import code.name.monkey.retromusic.util.MusicUtil
-import code.name.monkey.retromusic.util.RetroUtil
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.signature.MediaStoreSignature
import me.zhanghai.android.fastscroll.PopupTextProvider
import java.io.File
import java.text.DecimalFormat
-import java.util.*
import kotlin.math.log10
import kotlin.math.pow
class SongFileAdapter(
- private val activity: AppCompatActivity,
+ override val activity: AppCompatActivity,
private var dataSet: List,
private val itemLayoutRes: Int,
- private val callbacks: Callbacks?,
- cabHolder: CabHolder?
+ private val iCallbacks: ICallbacks?
) : AbsMultiSelectAdapter(
- activity, cabHolder, R.menu.menu_media_selection
+ activity, R.menu.menu_media_selection
), PopupTextProvider {
init {
@@ -78,7 +76,7 @@ class SongFileAdapter(
if (holder.itemViewType == FILE) {
holder.text?.text = getFileText(file)
} else {
- holder.text?.visibility = View.GONE
+ holder.text?.isVisible = false
}
}
@@ -96,30 +94,28 @@ class SongFileAdapter(
}
private fun loadFileImage(file: File, holder: ViewHolder) {
- val iconColor = ATHUtil.resolveColor(activity, R.attr.colorControlNormal)
+ val iconColor = ATHUtil.resolveColor(activity, androidx.appcompat.R.attr.colorControlNormal)
if (file.isDirectory) {
holder.image?.let {
it.setColorFilter(iconColor, PorterDuff.Mode.SRC_IN)
- it.setImageResource(R.drawable.ic_folder_white_24dp)
+ it.setImageResource(R.drawable.ic_folder)
}
holder.imageTextContainer?.setCardBackgroundColor(
ATHUtil.resolveColor(
activity,
- R.attr.colorSurface
+ com.google.android.material.R.attr.colorSurface
)
)
} else {
- val error = RetroUtil.getTintedVectorDrawable(
- activity, R.drawable.ic_file_music_white_24dp, iconColor
- )
+ val error = activity.getTintedDrawable(R.drawable.ic_audio_file, iconColor)
Glide.with(activity)
.load(AudioFileCover(file.path))
.diskCacheStrategy(DiskCacheStrategy.NONE)
.error(error)
.placeholder(error)
- .animate(android.R.anim.fade_in)
+ .transition(RetroGlideExtension.getDefaultTransition())
.signature(MediaStoreSignature("", file.lastModified(), 0))
- .into(holder.image)
+ .into(holder.image!!)
}
}
@@ -127,43 +123,35 @@ class SongFileAdapter(
return dataSet.size
}
- override fun getIdentifier(position: Int): File? {
+ override fun getIdentifier(position: Int): File {
return dataSet[position]
}
- override fun getName(`object`: File): String {
- return getFileTitle(`object`)
+ override fun getName(model: File): String {
+ return getFileTitle(model)
}
- override fun onMultipleItemAction(menuItem: MenuItem, selection: ArrayList) {
- if (callbacks == null) return
- callbacks.onMultipleItemAction(menuItem, selection)
+ override fun onMultipleItemAction(menuItem: MenuItem, selection: List) {
+ if (iCallbacks == null) return
+ iCallbacks.onMultipleItemAction(menuItem, selection as ArrayList)
}
override fun getPopupText(position: Int): String {
- return getSectionName(position)
+ return if (position >= dataSet.lastIndex) "" else getSectionName(position)
}
private fun getSectionName(position: Int): String {
return MusicUtil.getSectionName(dataSet[position].name)
}
- interface Callbacks {
- fun onFileSelected(file: File)
-
- fun onFileMenuClicked(file: File, view: View)
-
- fun onMultipleItemAction(item: MenuItem, files: ArrayList)
- }
-
- inner class ViewHolder(itemView: View) : MediaEntryViewHolder(itemView) {
+ inner class ViewHolder(itemView: View) : code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder(itemView) {
init {
- if (menu != null && callbacks != null) {
+ if (menu != null && iCallbacks != null) {
menu?.setOnClickListener { v ->
val position = layoutPosition
if (isPositionInRange(position)) {
- callbacks.onFileMenuClicked(dataSet[position], v)
+ iCallbacks.onFileMenuClicked(dataSet[position], v)
}
}
}
@@ -178,7 +166,7 @@ class SongFileAdapter(
if (isInQuickSelectMode) {
toggleChecked(position)
} else {
- callbacks?.onFileSelected(dataSet[position])
+ iCallbacks?.onFileSelected(dataSet[position])
}
}
}
@@ -205,4 +193,4 @@ class SongFileAdapter(
return DecimalFormat("#,##0.##").format(size / 1024.0.pow(digitGroups.toDouble())) + " " + units[digitGroups]
}
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/StorageAdapter.kt b/app/src/main/java/code/name/monkey/retromusic/adapter/StorageAdapter.kt
new file mode 100644
index 000000000..98c2c632f
--- /dev/null
+++ b/app/src/main/java/code/name/monkey/retromusic/adapter/StorageAdapter.kt
@@ -0,0 +1,55 @@
+package code.name.monkey.retromusic.adapter
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import code.name.monkey.retromusic.R
+import java.io.File
+
+class StorageAdapter(
+ val storageList: List,
+ val storageClickListener: StorageClickListener
+) :
+ RecyclerView.Adapter() {
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ return ViewHolder(
+ LayoutInflater.from(parent.context).inflate(
+ R.layout.item_storage,
+ parent,
+ false
+ )
+ )
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ holder.bindData(storageList[position])
+ }
+
+ override fun getItemCount(): Int {
+ return storageList.size
+ }
+
+ inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+ val title: TextView = itemView.findViewById(R.id.title)
+
+ fun bindData(storage: Storage) {
+ title.text = storage.title
+ }
+
+ init {
+ itemView.setOnClickListener { storageClickListener.onStorageClicked(storageList[bindingAdapterPosition]) }
+ }
+ }
+}
+
+interface StorageClickListener {
+ fun onStorageClicked(storage: Storage)
+}
+
+class Storage {
+ lateinit var title: String
+ lateinit var file: File
+}
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/TranslatorsAdapter.kt b/app/src/main/java/code/name/monkey/retromusic/adapter/TranslatorsAdapter.kt
deleted file mode 100644
index 90585c364..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/adapter/TranslatorsAdapter.kt
+++ /dev/null
@@ -1,52 +0,0 @@
-package code.name.monkey.retromusic.adapter
-
-import android.app.Activity
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.TextView
-import androidx.recyclerview.widget.RecyclerView
-import code.name.monkey.retromusic.R
-import code.name.monkey.retromusic.extensions.hide
-import code.name.monkey.retromusic.model.Contributor
-import code.name.monkey.retromusic.util.RetroUtil
-import code.name.monkey.retromusic.views.RetroShapeableImageView
-
-class TranslatorsAdapter(
- private var contributors: List
-) : RecyclerView.Adapter() {
-
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
- return ViewHolder(
- LayoutInflater.from(parent.context).inflate(
- R.layout.item_contributor,
- parent,
- false
- )
- )
- }
-
- override fun onBindViewHolder(holder: ViewHolder, position: Int) {
- val contributor = contributors[position]
- holder.bindData(contributor)
- holder.itemView.setOnClickListener {
- RetroUtil.openUrl(it?.context as Activity, contributors[position].link)
- }
- }
-
- override fun getItemCount(): Int {
- return contributors.size
- }
-
- inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
- val title: TextView = itemView.findViewById(R.id.title)
- val text: TextView = itemView.findViewById(R.id.text)
- val image: RetroShapeableImageView = itemView.findViewById(R.id.icon)
-
- internal fun bindData(contributor: Contributor) {
- title.text = contributor.name
- text.text = contributor.summary
- image.hide()
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/album/AlbumAdapter.kt b/app/src/main/java/code/name/monkey/retromusic/adapter/album/AlbumAdapter.kt
index 3841fd9eb..160af7e47 100644
--- a/app/src/main/java/code/name/monkey/retromusic/adapter/album/AlbumAdapter.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/adapter/album/AlbumAdapter.kt
@@ -1,40 +1,51 @@
+/*
+ * Copyright (c) 2020 Hemanth Savarla.
+ *
+ * Licensed under the GNU General Public License v3
+ *
+ * This is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ */
package code.name.monkey.retromusic.adapter.album
-import android.app.ActivityOptions
import android.content.res.ColorStateList
-import android.content.res.Resources
-import android.graphics.drawable.Drawable
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
-import androidx.appcompat.app.AppCompatActivity
+import androidx.core.view.isVisible
+import androidx.fragment.app.FragmentActivity
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.base.AbsMultiSelectAdapter
import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder
-import code.name.monkey.retromusic.glide.AlbumGlideRequest
+import code.name.monkey.retromusic.glide.RetroGlideExtension
+import code.name.monkey.retromusic.glide.RetroGlideExtension.albumCoverOptions
+import code.name.monkey.retromusic.glide.RetroGlideExtension.asBitmapPalette
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
-import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.SortOrder
import code.name.monkey.retromusic.helper.menu.SongsMenuHelper
-import code.name.monkey.retromusic.interfaces.CabHolder
+import code.name.monkey.retromusic.interfaces.IAlbumClickListener
import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.MusicUtil
-import code.name.monkey.retromusic.util.NavigationUtil
import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.bumptech.glide.Glide
import me.zhanghai.android.fastscroll.PopupTextProvider
open class AlbumAdapter(
- protected val activity: AppCompatActivity,
+ override val activity: FragmentActivity,
var dataSet: List,
- protected var itemLayoutRes: Int,
- cabHolder: CabHolder?
+ var itemLayoutRes: Int,
+ val listener: IAlbumClickListener?
) : AbsMultiSelectAdapter(
activity,
- cabHolder,
R.menu.menu_media_selection
), PopupTextProvider {
@@ -48,12 +59,7 @@ open class AlbumAdapter(
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
- val view =
- try {
- LayoutInflater.from(activity).inflate(itemLayoutRes, parent, false)
- } catch (e: Resources.NotFoundException) {
- LayoutInflater.from(activity).inflate(R.layout.item_grid, parent, false)
- }
+ val view = LayoutInflater.from(activity).inflate(itemLayoutRes, parent, false)
return createViewHolder(view, viewType)
}
@@ -61,12 +67,18 @@ open class AlbumAdapter(
return ViewHolder(view)
}
- private fun getAlbumTitle(album: Album): String? {
+ private fun getAlbumTitle(album: Album): String {
return album.title
}
protected open fun getAlbumText(album: Album): String? {
- return album.artistName
+ return album.albumArtist.let {
+ if (it.isNullOrEmpty()) {
+ album.artistName
+ } else {
+ it
+ }
+ }
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
@@ -75,14 +87,12 @@ open class AlbumAdapter(
holder.itemView.isActivated = isChecked
holder.title?.text = getAlbumTitle(album)
holder.text?.text = getAlbumText(album)
- holder.playSongs?.setOnClickListener {
- album.songs?.let { songs ->
- MusicPlayerRemote.openQueue(
- songs,
- 0,
- true
- )
- }
+ // Check if imageContainer exists so we can have a smooth transition without
+ // CardView clipping, if it doesn't exist in current layout set transition name to image instead.
+ if (holder.imageContainer != null) {
+ holder.imageContainer?.transitionName = album.id.toString()
+ } else {
+ holder.image?.transitionName = album.id.toString()
}
loadAlbumCover(album, holder)
}
@@ -94,23 +104,20 @@ open class AlbumAdapter(
holder.paletteColorContainer?.setBackgroundColor(color.backgroundColor)
}
holder.mask?.backgroundTintList = ColorStateList.valueOf(color.primaryTextColor)
+ holder.imageContainerCard?.setCardBackgroundColor(color.backgroundColor)
}
protected open fun loadAlbumCover(album: Album, holder: ViewHolder) {
if (holder.image == null) {
return
}
-
- AlbumGlideRequest.Builder.from(Glide.with(activity), album.safeGetFirstSong())
- .checkIgnoreMediaStore(activity)
- .generatePalette(activity)
- .build()
+ val song = album.safeGetFirstSong()
+ Glide.with(activity)
+ .asBitmapPalette()
+ .albumCoverOptions(song)
+ //.checkIgnoreMediaStore()
+ .load(RetroGlideExtension.getSongModel(song))
.into(object : RetroMusicColoredTarget(holder.image!!) {
- override fun onLoadCleared(placeholder: Drawable?) {
- super.onLoadCleared(placeholder)
- //setColors(defaultFooterColor, holder)
- }
-
override fun onColorReady(colors: MediaNotificationProcessor) {
setColors(colors, holder)
}
@@ -122,27 +129,28 @@ open class AlbumAdapter(
}
override fun getItemId(position: Int): Long {
- return dataSet[position].id.toLong()
+ return dataSet[position].id
}
override fun getIdentifier(position: Int): Album? {
return dataSet[position]
}
- override fun getName(album: Album): String {
- return album.title!!
+ override fun getName(model: Album): String {
+ return model.title
}
override fun onMultipleItemAction(
- menuItem: MenuItem, selection: ArrayList
+ menuItem: MenuItem,
+ selection: List
) {
SongsMenuHelper.handleMenuClick(activity, getSongList(selection), menuItem.itemId)
}
- private fun getSongList(albums: List): ArrayList {
+ private fun getSongList(albums: List): List {
val songs = ArrayList()
for (album in albums) {
- songs.addAll(album.songs!!)
+ songs.addAll(album.songs)
}
return songs
}
@@ -156,20 +164,19 @@ open class AlbumAdapter(
when (PreferenceUtil.albumSortOrder) {
SortOrder.AlbumSortOrder.ALBUM_A_Z, SortOrder.AlbumSortOrder.ALBUM_Z_A -> sectionName =
dataSet[position].title
- SortOrder.AlbumSortOrder.ALBUM_ARTIST -> sectionName = dataSet[position].artistName
+
+ SortOrder.AlbumSortOrder.ALBUM_ARTIST -> sectionName = dataSet[position].albumArtist
SortOrder.AlbumSortOrder.ALBUM_YEAR -> return MusicUtil.getYearString(
dataSet[position].year
)
}
-
return MusicUtil.getSectionName(sectionName)
}
inner class ViewHolder(itemView: View) : MediaEntryViewHolder(itemView) {
init {
- setImageTransitionName(activity.getString(R.string.transition_album_art))
- menu?.visibility = View.GONE
+ menu?.isVisible = false
}
override fun onClick(v: View?) {
@@ -177,22 +184,14 @@ open class AlbumAdapter(
if (isInQuickSelectMode) {
toggleChecked(layoutPosition)
} else {
- val activityOptions = ActivityOptions.makeSceneTransitionAnimation(
- activity,
- imageContainerCard ?: image,
- activity.getString(R.string.transition_album_art)
- )
- NavigationUtil.goToAlbumOptions(
- activity,
- dataSet[layoutPosition].id,
- activityOptions
- )
+ image?.let {
+ listener?.onAlbumClick(dataSet[layoutPosition].id, imageContainer ?: it)
+ }
}
}
override fun onLongClick(v: View?): Boolean {
- toggleChecked(layoutPosition)
- return super.onLongClick(v)
+ return toggleChecked(layoutPosition)
}
}
diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/album/AlbumCoverPagerAdapter.kt b/app/src/main/java/code/name/monkey/retromusic/adapter/album/AlbumCoverPagerAdapter.kt
index a504cc814..5a0a7d3cd 100644
--- a/app/src/main/java/code/name/monkey/retromusic/adapter/album/AlbumCoverPagerAdapter.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/adapter/album/AlbumCoverPagerAdapter.kt
@@ -1,3 +1,17 @@
+/*
+ * Copyright (c) 2020 Hemanth Savarla.
+ *
+ * Licensed under the GNU General Public License v3
+ *
+ * This is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ */
package code.name.monkey.retromusic.adapter.album
import android.os.Bundle
@@ -5,20 +19,31 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
+import androidx.core.os.BundleCompat
+import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
+import androidx.lifecycle.lifecycleScope
import code.name.monkey.retromusic.R
+import code.name.monkey.retromusic.activities.MainActivity
import code.name.monkey.retromusic.fragments.AlbumCoverStyle
import code.name.monkey.retromusic.fragments.NowPlayingScreen.*
+import code.name.monkey.retromusic.fragments.base.goToLyrics
+import code.name.monkey.retromusic.glide.RetroGlideExtension
+import code.name.monkey.retromusic.glide.RetroGlideExtension.asBitmapPalette
+import code.name.monkey.retromusic.glide.RetroGlideExtension.songCoverOptions
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
-import code.name.monkey.retromusic.glide.SongGlideRequest
import code.name.monkey.retromusic.misc.CustomFragmentStatePagerAdapter
import code.name.monkey.retromusic.model.Song
-import code.name.monkey.retromusic.util.NavigationUtil
-
+import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.bumptech.glide.Glide
+import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
class AlbumCoverPagerAdapter(
fragmentManager: FragmentManager,
@@ -63,17 +88,17 @@ class AlbumCoverPagerAdapter(
class AlbumCoverFragment : Fragment() {
- lateinit var albumCover: ImageView
private var isColorReady: Boolean = false
private lateinit var color: MediaNotificationProcessor
private lateinit var song: Song
private var colorReceiver: ColorReceiver? = null
private var request: Int = 0
+ private val mainActivity get() = activity as MainActivity
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (arguments != null) {
- song = requireArguments().getParcelable(SONG_ARG)!!
+ song = BundleCompat.getParcelable(requireArguments(), SONG_ARG, Song::class.java)!!
}
}
@@ -83,22 +108,37 @@ class AlbumCoverPagerAdapter(
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(getLayoutWithPlayerTheme(), container, false)
- albumCover = view.findViewById(R.id.player_image)
- albumCover.setOnClickListener {
- NavigationUtil.goToLyrics(requireActivity())
+ view.setOnClickListener {
+ if (mainActivity.getBottomSheetBehavior().state == STATE_EXPANDED) {
+ showLyricsDialog()
+ }
}
return view
}
+ private fun showLyricsDialog() {
+ lifecycleScope.launch(Dispatchers.IO) {
+ val data: String? = MusicUtil.getLyrics(song)
+ withContext(Dispatchers.Main) {
+ MaterialAlertDialogBuilder(
+ requireContext(),
+ com.google.android.material.R.style.ThemeOverlay_MaterialComponents_Dialog_Alert
+ ).apply {
+ setTitle(song.title)
+ setMessage(if (data.isNullOrEmpty()) "No lyrics found" else data)
+ setNegativeButton(R.string.synced_lyrics) { _, _ ->
+ goToLyrics(requireActivity())
+ }
+ show()
+ }
+ }
+ }
+ }
+
private fun getLayoutWithPlayerTheme(): Int {
return when (PreferenceUtil.nowPlayingScreen) {
- Card,
- Fit,
- Tiny,
- Classic,
- Peak,
- Gradient,
- Full -> R.layout.fragment_album_full_cover
+ Card, Fit, Tiny, Classic, Gradient, Full -> R.layout.fragment_album_full_cover
+ Peek -> R.layout.fragment_peek_album_cover
else -> {
if (PreferenceUtil.isCarouselEffect) {
R.layout.fragment_album_carousel_cover
@@ -108,7 +148,6 @@ class AlbumCoverPagerAdapter(
AlbumCoverStyle.Flat -> R.layout.fragment_album_flat_cover
AlbumCoverStyle.Circle -> R.layout.fragment_album_circle_cover
AlbumCoverStyle.Card -> R.layout.fragment_album_card_cover
- AlbumCoverStyle.Material -> R.layout.fragment_album_material_cover
AlbumCoverStyle.Full -> R.layout.fragment_album_full_cover
AlbumCoverStyle.FullCard -> R.layout.fragment_album_full_card_cover
}
@@ -119,7 +158,7 @@ class AlbumCoverPagerAdapter(
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- loadAlbumCover()
+ loadAlbumCover(albumCover = view.findViewById(R.id.player_image))
}
override fun onDestroyView() {
@@ -127,10 +166,13 @@ class AlbumCoverPagerAdapter(
colorReceiver = null
}
- private fun loadAlbumCover() {
- SongGlideRequest.Builder.from(Glide.with(requireContext()), song)
- .checkIgnoreMediaStore(requireContext())
- .generatePalette(requireContext()).build()
+ private fun loadAlbumCover(albumCover: ImageView) {
+ Glide.with(this)
+ .asBitmapPalette()
+ .songCoverOptions(song)
+ //.checkIgnoreMediaStore()
+ .load(RetroGlideExtension.getSongModel(song))
+ .dontAnimate()
.into(object : RetroMusicColoredTarget(albumCover) {
override fun onColorReady(colors: MediaNotificationProcessor) {
setColor(colors)
@@ -166,9 +208,7 @@ class AlbumCoverPagerAdapter(
fun newInstance(song: Song): AlbumCoverFragment {
val frag = AlbumCoverFragment()
- val args = Bundle()
- args.putParcelable(SONG_ARG, song)
- frag.arguments = args
+ frag.arguments = bundleOf(SONG_ARG to song)
return frag
}
}
@@ -178,4 +218,3 @@ class AlbumCoverPagerAdapter(
val TAG: String = AlbumCoverPagerAdapter::class.java.simpleName
}
}
-
diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/album/AlbumFullWidthAdapter.kt b/app/src/main/java/code/name/monkey/retromusic/adapter/album/AlbumFullWidthAdapter.kt
deleted file mode 100644
index 5a774b20b..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/adapter/album/AlbumFullWidthAdapter.kt
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2017. Alexander Bilchuk
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package code.name.monkey.retromusic.adapter.album
-
-import android.app.Activity
-import android.app.ActivityOptions
-import android.util.DisplayMetrics
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import code.name.monkey.retromusic.R
-import code.name.monkey.retromusic.glide.AlbumGlideRequest
-import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
-import code.name.monkey.retromusic.helper.MusicPlayerRemote
-import code.name.monkey.retromusic.model.Album
-import code.name.monkey.retromusic.util.NavigationUtil
-import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
-import code.name.monkey.retromusic.views.MetalRecyclerViewPager
-import com.bumptech.glide.Glide
-
-class AlbumFullWidthAdapter(
- private val activity: Activity,
- private val dataSet: List,
- metrics: DisplayMetrics
-) : MetalRecyclerViewPager.MetalAdapter(metrics) {
-
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FullMetalViewHolder {
- return FullMetalViewHolder(
- LayoutInflater.from(parent.context).inflate(
- R.layout.pager_item,
- parent,
- false
- )
- )
- }
-
- override fun onBindViewHolder(holder: FullMetalViewHolder, position: Int) {
- // don't forget about calling supper.onBindViewHolder!
- super.onBindViewHolder(holder, position)
- val album = dataSet[position]
- holder.title?.text = getAlbumTitle(album)
- holder.text?.text = getAlbumText(album)
- holder.playSongs?.setOnClickListener {
- album.songs?.let { songs ->
- MusicPlayerRemote.openQueue(
- songs,
- 0,
- true
- )
- }
- }
- loadAlbumCover(album, holder)
- }
-
- private fun getAlbumTitle(album: Album): String? {
- return album.title
- }
-
- private fun getAlbumText(album: Album): String? {
- return album.artistName
- }
-
- private fun loadAlbumCover(album: Album, holder: FullMetalViewHolder) {
- if (holder.image == null) {
- return
- }
-
- AlbumGlideRequest.Builder.from(Glide.with(activity), album.safeGetFirstSong())
- .checkIgnoreMediaStore(activity)
- .generatePalette(activity)
- .build()
- .into(object : RetroMusicColoredTarget(holder.image!!) {
- override fun onColorReady(colors: MediaNotificationProcessor) {
-
- }
- })
- }
-
- override fun getItemCount(): Int {
- return dataSet.size
- }
-
- inner class FullMetalViewHolder(itemView: View) :
- MetalRecyclerViewPager.MetalViewHolder(itemView) {
-
- override fun onClick(v: View?) {
- val activityOptions = ActivityOptions.makeSceneTransitionAnimation(
- activity,
- imageContainerCard ?: image,
- activity.getString(R.string.transition_album_art)
- )
- NavigationUtil.goToAlbumOptions(activity, dataSet[layoutPosition].id, activityOptions)
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/album/HorizontalAlbumAdapter.kt b/app/src/main/java/code/name/monkey/retromusic/adapter/album/HorizontalAlbumAdapter.kt
index c19221de4..7a9f7fa6e 100644
--- a/app/src/main/java/code/name/monkey/retromusic/adapter/album/HorizontalAlbumAdapter.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/adapter/album/HorizontalAlbumAdapter.kt
@@ -1,25 +1,39 @@
+/*
+ * Copyright (c) 2020 Hemanth Savarla.
+ *
+ * Licensed under the GNU General Public License v3
+ *
+ * This is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ */
package code.name.monkey.retromusic.adapter.album
-import android.graphics.drawable.Drawable
import android.view.View
import android.view.ViewGroup
-import androidx.appcompat.app.AppCompatActivity
-import code.name.monkey.appthemehelper.util.ATHUtil
-import code.name.monkey.retromusic.glide.AlbumGlideRequest
+import androidx.fragment.app.FragmentActivity
+import code.name.monkey.retromusic.glide.RetroGlideExtension
+import code.name.monkey.retromusic.glide.RetroGlideExtension.albumCoverOptions
+import code.name.monkey.retromusic.glide.RetroGlideExtension.asBitmapPalette
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
import code.name.monkey.retromusic.helper.HorizontalAdapterHelper
-import code.name.monkey.retromusic.interfaces.CabHolder
+import code.name.monkey.retromusic.interfaces.IAlbumClickListener
import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.bumptech.glide.Glide
class HorizontalAlbumAdapter(
- activity: AppCompatActivity,
+ activity: FragmentActivity,
dataSet: List,
- cabHolder: CabHolder?
+ albumClickListener: IAlbumClickListener
) : AlbumAdapter(
- activity, dataSet, HorizontalAdapterHelper.LAYOUT_RES, cabHolder
+ activity, dataSet, HorizontalAdapterHelper.LAYOUT_RES, albumClickListener
) {
override fun createViewHolder(view: View, viewType: Int): ViewHolder {
@@ -29,34 +43,29 @@ class HorizontalAlbumAdapter(
}
override fun setColors(color: MediaNotificationProcessor, holder: ViewHolder) {
- holder.title?.setTextColor(ATHUtil.resolveColor(activity, android.R.attr.textColorPrimary))
- holder.text?.setTextColor(ATHUtil.resolveColor(activity, android.R.attr.textColorSecondary))
+ // holder.title?.setTextColor(ATHUtil.resolveColor(activity, android.R.attr.textColorPrimary))
+ // holder.text?.setTextColor(ATHUtil.resolveColor(activity, android.R.attr.textColorSecondary))
}
override fun loadAlbumCover(album: Album, holder: ViewHolder) {
if (holder.image == null) return
- AlbumGlideRequest.Builder.from(Glide.with(activity), album.safeGetFirstSong())
- .checkIgnoreMediaStore(activity)
- .generatePalette(activity)
- .build()
+ Glide.with(activity)
+ .asBitmapPalette()
+ .albumCoverOptions(album.safeGetFirstSong())
+ .load(RetroGlideExtension.getSongModel(album.safeGetFirstSong()))
.into(object : RetroMusicColoredTarget(holder.image!!) {
- override fun onLoadCleared(placeholder: Drawable?) {
- super.onLoadCleared(placeholder)
- //setColors(albumArtistFooterColor, holder)
- }
-
override fun onColorReady(colors: MediaNotificationProcessor) {
setColors(colors, holder)
}
})
}
- override fun getAlbumText(album: Album): String? {
+ override fun getAlbumText(album: Album): String {
return MusicUtil.getYearString(album.year)
}
override fun getItemViewType(position: Int): Int {
- return HorizontalAdapterHelper.getItemViewtype(position, itemCount)
+ return HorizontalAdapterHelper.getItemViewType(position, itemCount)
}
override fun getItemCount(): Int {
diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/artist/ArtistAdapter.kt b/app/src/main/java/code/name/monkey/retromusic/adapter/artist/ArtistAdapter.kt
index 65aa15b5a..e1ea2ca4c 100644
--- a/app/src/main/java/code/name/monkey/retromusic/adapter/artist/ArtistAdapter.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/adapter/artist/ArtistAdapter.kt
@@ -1,50 +1,70 @@
+/*
+ * Copyright (c) 2020 Hemanth Savarla.
+ *
+ * Licensed under the GNU General Public License v3
+ *
+ * This is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ */
package code.name.monkey.retromusic.adapter.artist
-import android.app.ActivityOptions
+import android.annotation.SuppressLint
import android.content.res.ColorStateList
import android.content.res.Resources
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
-import androidx.appcompat.app.AppCompatActivity
+import androidx.core.view.isVisible
+import androidx.fragment.app.FragmentActivity
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.base.AbsMultiSelectAdapter
-import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder
import code.name.monkey.retromusic.extensions.hide
-import code.name.monkey.retromusic.glide.ArtistGlideRequest
+import code.name.monkey.retromusic.glide.RetroGlideExtension
+import code.name.monkey.retromusic.glide.RetroGlideExtension.artistImageOptions
+import code.name.monkey.retromusic.glide.RetroGlideExtension.asBitmapPalette
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
import code.name.monkey.retromusic.helper.menu.SongsMenuHelper
-import code.name.monkey.retromusic.interfaces.CabHolder
+import code.name.monkey.retromusic.interfaces.IAlbumArtistClickListener
+import code.name.monkey.retromusic.interfaces.IArtistClickListener
import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.MusicUtil
-import code.name.monkey.retromusic.util.NavigationUtil
+import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.bumptech.glide.Glide
import me.zhanghai.android.fastscroll.PopupTextProvider
-import java.util.*
class ArtistAdapter(
- val activity: AppCompatActivity,
+ override val activity: FragmentActivity,
var dataSet: List,
var itemLayoutRes: Int,
- cabHolder: CabHolder?
-) : AbsMultiSelectAdapter(
- activity, cabHolder, R.menu.menu_media_selection
-), PopupTextProvider {
+ val IArtistClickListener: IArtistClickListener,
+ val IAlbumArtistClickListener: IAlbumArtistClickListener? = null
+) : AbsMultiSelectAdapter(activity, R.menu.menu_media_selection),
+ PopupTextProvider {
+
+ var albumArtistsOnly = false
init {
this.setHasStableIds(true)
}
+ @SuppressLint("NotifyDataSetChanged")
fun swapDataSet(dataSet: List) {
this.dataSet = dataSet
notifyDataSetChanged()
+ albumArtistsOnly = PreferenceUtil.albumArtistsOnly
}
override fun getItemId(position: Int): Long {
- return dataSet[position].id.toLong()
+ return dataSet[position].id
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
@@ -67,10 +87,17 @@ class ArtistAdapter(
holder.itemView.isActivated = isChecked
holder.title?.text = artist.name
holder.text?.hide()
+ val transitionName =
+ if (albumArtistsOnly) artist.name else artist.id.toString()
+ if (holder.imageContainer != null) {
+ holder.imageContainer?.transitionName = transitionName
+ } else {
+ holder.image?.transitionName = transitionName
+ }
loadArtistImage(artist, holder)
}
- fun setColors(processor: MediaNotificationProcessor, holder: ViewHolder) {
+ private fun setColors(processor: MediaNotificationProcessor, holder: ViewHolder) {
holder.mask?.backgroundTintList = ColorStateList.valueOf(processor.primaryTextColor)
if (holder.paletteColorContainer != null) {
holder.paletteColorContainer?.setBackgroundColor(processor.backgroundColor)
@@ -83,9 +110,11 @@ class ArtistAdapter(
if (holder.image == null) {
return
}
- ArtistGlideRequest.Builder.from(Glide.with(activity), artist)
- .generatePalette(activity)
- .build()
+ Glide.with(activity)
+ .asBitmapPalette()
+ .artistImageOptions(artist)
+ .load(RetroGlideExtension.getArtistModel(artist))
+ .transition(RetroGlideExtension.getDefaultTransition())
.into(object : RetroMusicColoredTarget(holder.image!!) {
override fun onColorReady(colors: MediaNotificationProcessor) {
setColors(colors, holder)
@@ -97,21 +126,22 @@ class ArtistAdapter(
return dataSet.size
}
- override fun getIdentifier(position: Int): Artist? {
+ override fun getIdentifier(position: Int): Artist {
return dataSet[position]
}
- override fun getName(artist: Artist): String {
- return artist.name
+ override fun getName(model: Artist): String {
+ return model.name
}
override fun onMultipleItemAction(
- menuItem: MenuItem, selection: ArrayList
+ menuItem: MenuItem,
+ selection: List
) {
SongsMenuHelper.handleMenuClick(activity, getSongList(selection), menuItem.itemId)
}
- private fun getSongList(artists: List): ArrayList {
+ private fun getSongList(artists: List): List {
val songs = ArrayList()
for (artist in artists) {
songs.addAll(artist.songs) // maybe async in future?
@@ -127,11 +157,10 @@ class ArtistAdapter(
return MusicUtil.getSectionName(dataSet[position].name)
}
- inner class ViewHolder(itemView: View) : MediaEntryViewHolder(itemView) {
+ inner class ViewHolder(itemView: View) : code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder(itemView) {
init {
- setImageTransitionName(activity.getString(R.string.transition_artist_image))
- menu?.visibility = View.GONE
+ menu?.isVisible = false
}
override fun onClick(v: View?) {
@@ -139,20 +168,19 @@ class ArtistAdapter(
if (isInQuickSelectMode) {
toggleChecked(layoutPosition)
} else {
- val activityOptions = ActivityOptions.makeSceneTransitionAnimation(
- activity,
- imageContainerCard ?: image,
- activity.getString(R.string.transition_artist_image)
- )
- NavigationUtil.goToArtistOptions(
- activity, dataSet[layoutPosition].id, activityOptions
- )
+ val artist = dataSet[layoutPosition]
+ image?.let {
+ if (albumArtistsOnly && IAlbumArtistClickListener != null) {
+ IAlbumArtistClickListener.onAlbumArtist(artist.name, imageContainer ?: it)
+ } else {
+ IArtistClickListener.onArtist(artist.id, imageContainer ?: it)
+ }
+ }
}
}
override fun onLongClick(v: View?): Boolean {
- toggleChecked(layoutPosition)
- return super.onLongClick(v)
+ return toggleChecked(layoutPosition)
}
}
}
diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/backup/BackupAdapter.kt b/app/src/main/java/code/name/monkey/retromusic/adapter/backup/BackupAdapter.kt
new file mode 100644
index 000000000..adfcecf1b
--- /dev/null
+++ b/app/src/main/java/code/name/monkey/retromusic/adapter/backup/BackupAdapter.kt
@@ -0,0 +1,65 @@
+package code.name.monkey.retromusic.adapter.backup
+
+import android.annotation.SuppressLint
+import android.view.LayoutInflater
+import android.view.MenuItem
+import android.view.ViewGroup
+import androidx.appcompat.widget.PopupMenu
+import androidx.fragment.app.FragmentActivity
+import androidx.recyclerview.widget.RecyclerView
+import code.name.monkey.retromusic.R
+import code.name.monkey.retromusic.databinding.ItemListBackupBinding
+import java.io.File
+
+
+class BackupAdapter(
+ val activity: FragmentActivity,
+ var dataSet: MutableList,
+ val backupClickedListener: BackupClickedListener
+) : RecyclerView.Adapter() {
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ return ViewHolder(
+ ItemListBackupBinding.inflate(LayoutInflater.from(activity), parent, false)
+ )
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ holder.binding.title.text = dataSet[position].nameWithoutExtension
+ }
+
+ override fun getItemCount(): Int = dataSet.size
+
+ @SuppressLint("NotifyDataSetChanged")
+ fun swapDataset(dataSet: List) {
+ this.dataSet = ArrayList(dataSet)
+ notifyDataSetChanged()
+ }
+
+ inner class ViewHolder(val binding: ItemListBackupBinding) :
+ RecyclerView.ViewHolder(binding.root) {
+
+ init {
+ binding.menu.setOnClickListener { view ->
+ val popupMenu = PopupMenu(activity, view)
+ popupMenu.inflate(R.menu.menu_backup)
+ popupMenu.setOnMenuItemClickListener { menuItem ->
+ return@setOnMenuItemClickListener backupClickedListener.onBackupMenuClicked(
+ dataSet[bindingAdapterPosition],
+ menuItem
+ )
+ }
+ popupMenu.show()
+ }
+ itemView.setOnClickListener {
+ backupClickedListener.onBackupClicked(dataSet[bindingAdapterPosition])
+ }
+ }
+ }
+
+ interface BackupClickedListener {
+ fun onBackupClicked(file: File)
+
+ fun onBackupMenuClicked(file: File, menuItem: MenuItem): Boolean
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/base/AbsMultiSelectAdapter.java b/app/src/main/java/code/name/monkey/retromusic/adapter/base/AbsMultiSelectAdapter.java
deleted file mode 100644
index 2aebe6c92..000000000
--- a/app/src/main/java/code/name/monkey/retromusic/adapter/base/AbsMultiSelectAdapter.java
+++ /dev/null
@@ -1,133 +0,0 @@
-package code.name.monkey.retromusic.adapter.base;
-
-import android.content.Context;
-import android.view.Menu;
-import android.view.MenuItem;
-
-import androidx.annotation.MenuRes;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.afollestad.materialcab.MaterialCab;
-
-import java.util.ArrayList;
-
-import code.name.monkey.retromusic.R;
-import code.name.monkey.retromusic.interfaces.CabHolder;
-
-
-public abstract class AbsMultiSelectAdapter extends RecyclerView.Adapter
- implements MaterialCab.Callback {
-
- @Nullable
- private final CabHolder cabHolder;
- private final Context context;
- private MaterialCab cab;
- private ArrayList checked;
- private int menuRes;
-
- public AbsMultiSelectAdapter(@NonNull Context context, @Nullable CabHolder cabHolder, @MenuRes int menuRes) {
- this.cabHolder = cabHolder;
- checked = new ArrayList<>();
- this.menuRes = menuRes;
- this.context = context;
- }
-
- @Override
- public boolean onCabCreated(MaterialCab materialCab, Menu menu) {
- return true;
- }
-
- @Override
- public boolean onCabFinished(MaterialCab materialCab) {
- clearChecked();
- return true;
- }
-
- @Override
- public boolean onCabItemClicked(MenuItem menuItem) {
- if (menuItem.getItemId() == R.id.action_multi_select_adapter_check_all) {
- checkAll();
- } else {
- onMultipleItemAction(menuItem, new ArrayList<>(checked));
- cab.finish();
- clearChecked();
- }
- return true;
- }
-
- protected void checkAll() {
- if (cabHolder != null) {
- checked.clear();
- for (int i = 0; i < getItemCount(); i++) {
- I identifier = getIdentifier(i);
- if (identifier != null) {
- checked.add(identifier);
- }
- }
- notifyDataSetChanged();
- updateCab();
- }
- }
-
- @Nullable
- protected abstract I getIdentifier(int position);
-
- protected String getName(I object) {
- return object.toString();
- }
-
- protected boolean isChecked(I identifier) {
- return checked.contains(identifier);
- }
-
- protected boolean isInQuickSelectMode() {
- return cab != null && cab.isActive();
- }
-
- protected abstract void onMultipleItemAction(MenuItem menuItem, ArrayList selection);
-
- protected void setMultiSelectMenuRes(@MenuRes int menuRes) {
- this.menuRes = menuRes;
- }
-
- protected boolean toggleChecked(final int position) {
- if (cabHolder != null) {
- I identifier = getIdentifier(position);
- if (identifier == null) {
- return false;
- }
-
- if (!checked.remove(identifier)) {
- checked.add(identifier);
- }
-
- notifyItemChanged(position);
- updateCab();
- return true;
- }
- return false;
- }
-
- private void clearChecked() {
- checked.clear();
- notifyDataSetChanged();
- }
-
- private void updateCab() {
- if (cabHolder != null) {
- if (cab == null || !cab.isActive()) {
- cab = cabHolder.openCab(menuRes, this);
- }
- final int size = checked.size();
- if (size <= 0) {
- cab.finish();
- } else if (size == 1) {
- cab.setTitle(getName(checked.get(0)));
- } else {
- cab.setTitle(context.getString(R.string.x_selected, size));
- }
- }
- }
-}
diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/base/AbsMultiSelectAdapter.kt b/app/src/main/java/code/name/monkey/retromusic/adapter/base/AbsMultiSelectAdapter.kt
new file mode 100644
index 000000000..bb7b8491c
--- /dev/null
+++ b/app/src/main/java/code/name/monkey/retromusic/adapter/base/AbsMultiSelectAdapter.kt
@@ -0,0 +1,131 @@
+package code.name.monkey.retromusic.adapter.base
+
+import android.graphics.Color
+import android.view.ActionMode
+import android.view.Menu
+import android.view.MenuItem
+import androidx.activity.OnBackPressedCallback
+import androidx.annotation.MenuRes
+import androidx.fragment.app.FragmentActivity
+import androidx.recyclerview.widget.RecyclerView
+import code.name.monkey.appthemehelper.util.VersionUtils
+import code.name.monkey.retromusic.R
+import code.name.monkey.retromusic.databinding.NumberRollViewBinding
+import code.name.monkey.retromusic.views.NumberRollView
+
+abstract class AbsMultiSelectAdapter(
+ open val activity: FragmentActivity, @MenuRes menuRes: Int,
+) : RecyclerView.Adapter(), ActionMode.Callback {
+ var actionMode: ActionMode? = null
+ private val checked: MutableList
+ private var menuRes: Int
+
+ override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
+ val inflater = mode?.menuInflater
+ inflater?.inflate(menuRes, menu)
+ return true
+ }
+
+ override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean {
+ return false
+ }
+
+ override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean {
+ if (item?.itemId == R.id.action_multi_select_adapter_check_all) {
+ checkAll()
+ } else {
+ onMultipleItemAction(item!!, ArrayList(checked))
+ actionMode?.finish()
+ clearChecked()
+ }
+ return true
+ }
+
+ override fun onDestroyActionMode(mode: ActionMode?) {
+ clearChecked()
+ activity.window.statusBarColor = when {
+ VersionUtils.hasMarshmallow() -> Color.TRANSPARENT
+ else -> Color.BLACK
+ }
+ actionMode = null
+ onBackPressedCallback.remove()
+ }
+
+ private fun checkAll() {
+ if (actionMode != null) {
+ checked.clear()
+ for (i in 0 until itemCount) {
+ val identifier = getIdentifier(i)
+ if (identifier != null) {
+ checked.add(identifier)
+ }
+ }
+ notifyDataSetChanged()
+ updateCab()
+ }
+ }
+
+ protected abstract fun getIdentifier(position: Int): I?
+
+ protected abstract fun getName(model: I): String?
+
+ protected fun isChecked(identifier: I): Boolean {
+ return checked.contains(identifier)
+ }
+
+ protected val isInQuickSelectMode: Boolean
+ get() = actionMode != null
+
+ protected abstract fun onMultipleItemAction(menuItem: MenuItem, selection: List)
+ protected fun setMultiSelectMenuRes(@MenuRes menuRes: Int) {
+ this.menuRes = menuRes
+ }
+
+ protected fun toggleChecked(position: Int): Boolean {
+ val identifier = getIdentifier(position) ?: return false
+ if (!checked.remove(identifier)) {
+ checked.add(identifier)
+ }
+ notifyItemChanged(position)
+ updateCab()
+ return true
+ }
+
+ private fun clearChecked() {
+ checked.clear()
+ notifyDataSetChanged()
+ }
+
+ private fun updateCab() {
+ if (actionMode == null) {
+ actionMode = activity.startActionMode(this)?.apply {
+ customView = NumberRollViewBinding.inflate(activity.layoutInflater).root
+ }
+ activity.onBackPressedDispatcher.addCallback(onBackPressedCallback)
+ }
+ val size = checked.size
+ when {
+ size <= 0 -> {
+ actionMode?.finish()
+ }
+ else -> {
+ actionMode?.customView?.findViewById(R.id.selection_mode_number)
+ ?.setNumber(size, true)
+ }
+ }
+ }
+
+ init {
+ checked = ArrayList()
+ this.menuRes = menuRes
+ }
+
+ private val onBackPressedCallback = object : OnBackPressedCallback(true) {
+ override fun handleOnBackPressed() {
+ if (actionMode != null) {
+ actionMode?.finish()
+ remove()
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/base/MediaEntryViewHolder.java b/app/src/main/java/code/name/monkey/retromusic/adapter/base/MediaEntryViewHolder.java
index ddf99c210..d68186c0f 100644
--- a/app/src/main/java/code/name/monkey/retromusic/adapter/base/MediaEntryViewHolder.java
+++ b/app/src/main/java/code/name/monkey/retromusic/adapter/base/MediaEntryViewHolder.java
@@ -16,14 +16,13 @@ package code.name.monkey.retromusic.adapter.base;
import android.graphics.Color;
import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageButton;
+import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.recyclerview.widget.RecyclerView;
+import androidx.appcompat.widget.AppCompatImageView;
import com.google.android.material.card.MaterialCardView;
import com.h6ah4i.android.widget.advrecyclerview.utils.AbstractDraggableSwipeableItemViewHolder;
@@ -41,18 +40,13 @@ public class MediaEntryViewHolder extends AbstractDraggableSwipeableItemViewHold
@Nullable
public ImageView image;
- @Nullable
- public ImageView artistImage;
-
- @Nullable
- public ImageView playerImage;
-
- @Nullable
- public ViewGroup imageContainer;
@Nullable
public MaterialCardView imageContainerCard;
+ @Nullable
+ public FrameLayout imageContainer;
+
@Nullable
public TextView imageText;
@@ -63,20 +57,17 @@ public class MediaEntryViewHolder extends AbstractDraggableSwipeableItemViewHold
public View mask;
@Nullable
- public View menu;
+ public AppCompatImageView menu;
@Nullable
public View paletteColorContainer;
- @Nullable
- public ImageButton playSongs;
-
- @Nullable
- public RecyclerView recyclerView;
-
@Nullable
public TextView text;
+ @Nullable
+ public TextView text2;
+
@Nullable
public TextView time;
@@ -87,23 +78,20 @@ public class MediaEntryViewHolder extends AbstractDraggableSwipeableItemViewHold
super(itemView);
title = itemView.findViewById(R.id.title);
text = itemView.findViewById(R.id.text);
+ text2 = itemView.findViewById(R.id.text2);
image = itemView.findViewById(R.id.image);
- artistImage = itemView.findViewById(R.id.artistImage);
- playerImage = itemView.findViewById(R.id.player_image);
time = itemView.findViewById(R.id.time);
imageText = itemView.findViewById(R.id.imageText);
- imageContainer = itemView.findViewById(R.id.imageContainer);
imageTextContainer = itemView.findViewById(R.id.imageTextContainer);
imageContainerCard = itemView.findViewById(R.id.imageContainerCard);
+ imageContainer = itemView.findViewById(R.id.imageContainer);
menu = itemView.findViewById(R.id.menu);
dragView = itemView.findViewById(R.id.drag_view);
paletteColorContainer = itemView.findViewById(R.id.paletteColorContainer);
- recyclerView = itemView.findViewById(R.id.recycler_view);
mask = itemView.findViewById(R.id.mask);
- playSongs = itemView.findViewById(R.id.playSongs);
dummyContainer = itemView.findViewById(R.id.dummy_view);
if (imageContainerCard != null) {
@@ -113,6 +101,7 @@ public class MediaEntryViewHolder extends AbstractDraggableSwipeableItemViewHold
itemView.setOnLongClickListener(this);
}
+ @Nullable
@Override
public View getSwipeableContainerView() {
return null;
@@ -120,7 +109,6 @@ public class MediaEntryViewHolder extends AbstractDraggableSwipeableItemViewHold
@Override
public void onClick(View v) {
-
}
@Override
@@ -129,11 +117,12 @@ public class MediaEntryViewHolder extends AbstractDraggableSwipeableItemViewHold
}
public void setImageTransitionName(@NonNull String transitionName) {
- if (imageContainerCard != null) {
- imageContainerCard.setTransitionName(transitionName);
- }
- if (image != null) {
- image.setTransitionName(transitionName);
- }
+ itemView.setTransitionName(transitionName);
+ /* if (imageContainerCard != null) {
+ imageContainerCard.setTransitionName(transitionName);
+ }
+ if (image != null) {
+ image.setTransitionName(transitionName);
+ }*/
}
}
diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/playlist/LegacyPlaylistAdapter.kt b/app/src/main/java/code/name/monkey/retromusic/adapter/playlist/LegacyPlaylistAdapter.kt
new file mode 100644
index 000000000..19d681ecf
--- /dev/null
+++ b/app/src/main/java/code/name/monkey/retromusic/adapter/playlist/LegacyPlaylistAdapter.kt
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2020 Hemanth Savarla.
+ *
+ * Licensed under the GNU General Public License v3
+ *
+ * This is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ */
+package code.name.monkey.retromusic.adapter.playlist
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.FragmentActivity
+import androidx.recyclerview.widget.RecyclerView
+import code.name.monkey.retromusic.model.Playlist
+import code.name.monkey.retromusic.util.MusicUtil
+
+class LegacyPlaylistAdapter(
+ private val activity: FragmentActivity,
+ private var list: List,
+ private val layoutRes: Int,
+ private val playlistClickListener: PlaylistClickListener
+) :
+ RecyclerView.Adapter() {
+
+ fun swapData(list: List) {
+ this.list = list
+ notifyDataSetChanged()
+ }
+
+ class ViewHolder(itemView: View) : code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder(itemView)
+
+ override fun onCreateViewHolder(
+ parent: ViewGroup,
+ viewType: Int
+ ): ViewHolder {
+ return ViewHolder(
+ LayoutInflater.from(parent.context).inflate(layoutRes, parent, false)
+ )
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ val playlist: Playlist = list[position]
+ holder.title?.text = playlist.name
+ holder.text?.text = MusicUtil.getPlaylistInfoString(activity, playlist.getSongs())
+ holder.itemView.setOnClickListener {
+ playlistClickListener.onPlaylistClick(playlist)
+ }
+ }
+
+ override fun getItemCount(): Int {
+ return list.size
+ }
+
+ interface PlaylistClickListener {
+ fun onPlaylistClick(playlist: Playlist)
+ }
+}
diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/playlist/PlaylistAdapter.kt b/app/src/main/java/code/name/monkey/retromusic/adapter/playlist/PlaylistAdapter.kt
index f5bf2b7e7..6e5b0c001 100755
--- a/app/src/main/java/code/name/monkey/retromusic/adapter/playlist/PlaylistAdapter.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/adapter/playlist/PlaylistAdapter.kt
@@ -1,61 +1,70 @@
+/*
+ * Copyright (c) 2020 Hemanth Savarla.
+ *
+ * Licensed under the GNU General Public License v3
+ *
+ * This is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ */
package code.name.monkey.retromusic.adapter.playlist
-import android.graphics.Bitmap
import android.graphics.Color
import android.graphics.drawable.Drawable
-import android.os.AsyncTask
-import android.text.TextUtils
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
-import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.PopupMenu
-import code.name.monkey.appthemehelper.ThemeStore
+import androidx.core.view.isGone
+import androidx.core.view.setPadding
+import androidx.fragment.app.FragmentActivity
import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.base.AbsMultiSelectAdapter
-import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder
-import code.name.monkey.retromusic.extensions.hide
-import code.name.monkey.retromusic.extensions.show
+import code.name.monkey.retromusic.db.PlaylistEntity
+import code.name.monkey.retromusic.db.PlaylistWithSongs
+import code.name.monkey.retromusic.db.toSongs
+import code.name.monkey.retromusic.extensions.dipToPix
+import code.name.monkey.retromusic.glide.RetroGlideExtension.playlistOptions
+import code.name.monkey.retromusic.glide.playlistPreview.PlaylistPreview
+import code.name.monkey.retromusic.helper.SortOrder.PlaylistSortOrder
import code.name.monkey.retromusic.helper.menu.PlaylistMenuHelper
import code.name.monkey.retromusic.helper.menu.SongsMenuHelper
-import code.name.monkey.retromusic.interfaces.CabHolder
-import code.name.monkey.retromusic.loaders.PlaylistSongsLoader
-import code.name.monkey.retromusic.model.AbsCustomPlaylist
-import code.name.monkey.retromusic.model.Playlist
+import code.name.monkey.retromusic.interfaces.IPlaylistClickListener
import code.name.monkey.retromusic.model.Song
-import code.name.monkey.retromusic.model.smartplaylist.AbsSmartPlaylist
-import code.name.monkey.retromusic.util.AutoGeneratedPlaylistBitmap
import code.name.monkey.retromusic.util.MusicUtil
-import code.name.monkey.retromusic.util.NavigationUtil
-import code.name.monkey.retromusic.util.RetroColorUtil
-import java.util.*
+import code.name.monkey.retromusic.util.PreferenceUtil
+import com.bumptech.glide.Glide
+import me.zhanghai.android.fastscroll.PopupTextProvider
class PlaylistAdapter(
- private val activity: AppCompatActivity,
- var dataSet: List,
+ override val activity: FragmentActivity,
+ var dataSet: List,
private var itemLayoutRes: Int,
- cabHolder: CabHolder?
-) : AbsMultiSelectAdapter(
+ private val listener: IPlaylistClickListener
+) : AbsMultiSelectAdapter(
activity,
- cabHolder,
R.menu.menu_playlists_selection
-) {
-
+), PopupTextProvider {
init {
setHasStableIds(true)
}
- fun swapDataSet(dataSet: List) {
+ fun swapDataSet(dataSet: List) {
this.dataSet = dataSet
notifyDataSetChanged()
}
override fun getItemId(position: Int): Long {
- return dataSet[position].id.toLong()
+ return dataSet[position].playlistEntity.playListId
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
@@ -63,64 +72,65 @@ class PlaylistAdapter(
return createViewHolder(view)
}
- fun createViewHolder(view: View): ViewHolder {
+ private fun createViewHolder(view: View): ViewHolder {
return ViewHolder(view)
}
- private fun getPlaylistTitle(playlist: Playlist): String {
- return if (TextUtils.isEmpty(playlist.name)) "-" else playlist.name
+ private fun getPlaylistTitle(playlist: PlaylistEntity): String {
+ return playlist.playlistName.ifEmpty { "-" }
}
- private fun getPlaylistText(playlist: Playlist): String {
- return MusicUtil.getPlaylistInfoString(activity, getSongs(playlist))
+ private fun getPlaylistText(playlist: PlaylistWithSongs): String {
+ return MusicUtil.getPlaylistInfoString(activity, playlist.songs.toSongs())
+ }
+
+ override fun getPopupText(position: Int): String {
+ val sectionName: String = when (PreferenceUtil.playlistSortOrder) {
+ PlaylistSortOrder.PLAYLIST_A_Z, PlaylistSortOrder.PLAYLIST_Z_A -> dataSet[position].playlistEntity.playlistName
+ PlaylistSortOrder.PLAYLIST_SONG_COUNT, PlaylistSortOrder.PLAYLIST_SONG_COUNT_DESC -> dataSet[position].songs.size.toString()
+ else -> {
+ return ""
+ }
+ }
+ return MusicUtil.getSectionName(sectionName)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val playlist = dataSet[position]
holder.itemView.isActivated = isChecked(playlist)
- holder.title?.text = getPlaylistTitle(playlist)
+ holder.title?.text = getPlaylistTitle(playlist.playlistEntity)
holder.text?.text = getPlaylistText(playlist)
- holder.image?.setImageDrawable(getIconRes(playlist))
- val isChecked = isChecked(playlist)
- if (isChecked) {
- holder.menu?.hide()
+ holder.menu?.isGone = isChecked(playlist)
+ if (itemLayoutRes == R.layout.item_list) {
+ holder.image?.setPadding(activity.dipToPix(8F).toInt())
+ holder.image?.setImageDrawable(getIconRes())
} else {
- holder.menu?.show()
+ Glide.with(activity)
+ .load(PlaylistPreview(playlist))
+ .playlistOptions()
+ .into(holder.image!!)
}
- //PlaylistBitmapLoader(this, holder, playlist).execute()
}
- private fun getIconRes(playlist: Playlist): Drawable {
- return if (MusicUtil.isFavoritePlaylist(activity, playlist))
- TintHelper.createTintedDrawable(
- activity,
- R.drawable.ic_favorite_white_24dp,
- ThemeStore.accentColor(activity)
- )
- else TintHelper.createTintedDrawable(
- activity,
- R.drawable.ic_playlist_play_white_24dp,
- ATHUtil.resolveColor(activity, R.attr.colorControlNormal)
- )
- }
-
- override fun getItemViewType(position: Int): Int {
- return if (dataSet[position] is AbsSmartPlaylist) SMART_PLAYLIST else DEFAULT_PLAYLIST
- }
+ private fun getIconRes(): Drawable = TintHelper.createTintedDrawable(
+ activity,
+ R.drawable.ic_playlist_play,
+ ATHUtil.resolveColor(activity, android.R.attr.colorControlNormal)
+ )
override fun getItemCount(): Int {
return dataSet.size
}
- override fun getIdentifier(position: Int): Playlist? {
+ override fun getIdentifier(position: Int): PlaylistWithSongs {
return dataSet[position]
}
- override fun getName(playlist: Playlist): String {
- return playlist.name
+ override fun getName(model: PlaylistWithSongs): String {
+ return model.playlistEntity.playlistName
}
- override fun onMultipleItemAction(menuItem: MenuItem, selection: ArrayList) {
+ override fun onMultipleItemAction(menuItem: MenuItem, selection: List) {
when (menuItem.itemId) {
else -> SongsMenuHelper.handleMenuClick(
activity,
@@ -130,44 +140,21 @@ class PlaylistAdapter(
}
}
- private fun getSongList(playlists: List): ArrayList {
- val songs = ArrayList()
- for (playlist in playlists) {
- if (playlist is AbsCustomPlaylist) {
- songs.addAll(playlist.getSongs(activity))
- } else {
- songs.addAll(PlaylistSongsLoader.getPlaylistSongList(activity, playlist.id))
- }
+ private fun getSongList(playlists: List): List {
+ val songs = mutableListOf()
+ playlists.forEach {
+ songs.addAll(it.songs.toSongs())
}
return songs
}
- private fun getSongs(playlist: Playlist): ArrayList {
- val songs = ArrayList()
- if (playlist is AbsSmartPlaylist) {
- songs.addAll(playlist.getSongs(activity))
- } else {
- songs.addAll(PlaylistSongsLoader.getPlaylistSongList(activity, playlist.id))
- }
- return songs
- }
-
- inner class ViewHolder(itemView: View) : MediaEntryViewHolder(itemView) {
+ inner class ViewHolder(itemView: View) : code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder(itemView) {
init {
-
- image?.apply {
- val iconPadding =
- activity.resources.getDimensionPixelSize(R.dimen.list_item_image_icon_padding)
- setPadding(iconPadding, iconPadding, iconPadding, iconPadding)
- }
-
menu?.setOnClickListener { view ->
val popupMenu = PopupMenu(activity, view)
popupMenu.inflate(R.menu.menu_item_playlist)
popupMenu.setOnMenuItemClickListener { item ->
- PlaylistMenuHelper.handleMenuClick(
- activity, dataSet[layoutPosition], item
- )
+ PlaylistMenuHelper.handleMenuClick(activity, dataSet[layoutPosition], item)
}
popupMenu.show()
}
@@ -182,8 +169,8 @@ class PlaylistAdapter(
if (isInQuickSelectMode) {
toggleChecked(layoutPosition)
} else {
- val playlist = dataSet[layoutPosition]
- NavigationUtil.goToPlaylistNew(activity, playlist)
+ itemView.transitionName = "playlist"
+ listener.onPlaylistClick(dataSet[layoutPosition], itemView)
}
}
@@ -193,33 +180,7 @@ class PlaylistAdapter(
}
}
- class PlaylistBitmapLoader(
- private var adapter: PlaylistAdapter,
- private var viewHolder: ViewHolder,
- private var playlist: Playlist
- ) : AsyncTask() {
-
- override fun doInBackground(vararg params: Void?): Bitmap {
- val songs = PlaylistSongsLoader.getPlaylistSongList(adapter.activity, playlist)
- return AutoGeneratedPlaylistBitmap.getBitmap(adapter.activity, songs, false, false)
- }
-
- override fun onPostExecute(result: Bitmap?) {
- super.onPostExecute(result)
- viewHolder.image?.setImageBitmap(result)
- val color = RetroColorUtil.getColor(
- RetroColorUtil.generatePalette(
- result
- ),
- ATHUtil.resolveColor(adapter.activity, R.attr.colorSurface)
- )
- viewHolder.paletteColorContainer?.setBackgroundColor(color)
- }
- }
-
companion object {
val TAG: String = PlaylistAdapter::class.java.simpleName
- private const val SMART_PLAYLIST = 0
- private const val DEFAULT_PLAYLIST = 1
}
}
diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/song/AbsOffsetSongAdapter.kt b/app/src/main/java/code/name/monkey/retromusic/adapter/song/AbsOffsetSongAdapter.kt
index d1141341c..2d5fd724f 100644
--- a/app/src/main/java/code/name/monkey/retromusic/adapter/song/AbsOffsetSongAdapter.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/adapter/song/AbsOffsetSongAdapter.kt
@@ -1,21 +1,33 @@
+/*
+ * Copyright (c) 2020 Hemanth Savarla.
+ *
+ * Licensed under the GNU General Public License v3
+ *
+ * This is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ */
package code.name.monkey.retromusic.adapter.song
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.LayoutRes
-import androidx.appcompat.app.AppCompatActivity
+import androidx.fragment.app.FragmentActivity
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.helper.MusicPlayerRemote
-import code.name.monkey.retromusic.interfaces.CabHolder
import code.name.monkey.retromusic.model.Song
abstract class AbsOffsetSongAdapter(
- activity: AppCompatActivity,
+ activity: FragmentActivity,
dataSet: MutableList