diff --git a/app/build.gradle b/app/build.gradle index 7e92f3b..42f0a2b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -23,8 +23,8 @@ android { minSdkVersion 21 targetSdkVersion 35 compileSdk 35 - versionCode 45 - versionName "0.2.0" + versionCode 46 + versionName "0.2.1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e60a85b..1b10784 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -27,6 +27,7 @@ android:exported="false" /> = mutableSetOf() - val launcher = DetailedAppInfo.fromAppInfo( - AppInfo( - BuildConfig.APPLICATION_ID, - HomeActivity::class.java.name, - INVALID_USER - ), context - ) - launcher?.getRawInfo()?.let { hidden.add(it) } - Log.i(TAG,"Hiding ${launcher?.getRawInfo()}") + + if (!BuildConfig.DEBUG) { + val launcher = DetailedAppInfo.fromAppInfo( + AppInfo( + BuildConfig.APPLICATION_ID, + HomeActivity::class.java.name, + INVALID_USER + ), context + ) + launcher?.getRawInfo()?.let { hidden.add(it) } + Log.i(TAG, "Hiding ${launcher?.getRawInfo()}") + } LauncherPreferences.apps().hidden(hidden) Action.resetToDefaultActions(context) diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version4.kt b/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version4.kt index aaeeb18..a9ab3a1 100644 --- a/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version4.kt +++ b/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version4.kt @@ -21,7 +21,5 @@ fun migratePreferencesFromVersion4(context: Context) { ) ) ) - - LauncherPreferences.internal().versionCode(100) } \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/HomeActivity.kt b/app/src/main/java/de/jrpie/android/launcher/ui/HomeActivity.kt index 192a8e9..f501107 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/HomeActivity.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/HomeActivity.kt @@ -12,11 +12,10 @@ import android.view.MotionEvent import android.view.View import android.window.OnBackInvokedDispatcher import de.jrpie.android.launcher.Application -import de.jrpie.android.launcher.R import de.jrpie.android.launcher.actions.Action import de.jrpie.android.launcher.actions.Gesture import de.jrpie.android.launcher.actions.LauncherAction -import de.jrpie.android.launcher.databinding.HomeBinding +import de.jrpie.android.launcher.databinding.ActivityHomeBinding import de.jrpie.android.launcher.openTutorial import de.jrpie.android.launcher.preferences.LauncherPreferences import de.jrpie.android.launcher.ui.tutorial.TutorialActivity @@ -35,7 +34,7 @@ import de.jrpie.android.launcher.ui.tutorial.TutorialActivity */ class HomeActivity : UIObject, Activity() { - private lateinit var binding: HomeBinding + private lateinit var binding: ActivityHomeBinding private var touchGestureDetector: TouchGestureDetector? = null private var sharedPreferencesListener = @@ -60,7 +59,7 @@ class HomeActivity : UIObject, Activity() { // Initialise layout - binding = HomeBinding.inflate(layoutInflater) + binding = ActivityHomeBinding.inflate(layoutInflater) setContentView(binding.root) @@ -129,15 +128,7 @@ class HomeActivity : UIObject, Activity() { } override fun getTheme(): Resources.Theme { - val mTheme = modifyTheme(super.getTheme()) - mTheme.applyStyle(R.style.backgroundWallpaper, true) - LauncherPreferences.clock().font().applyToTheme(mTheme) - LauncherPreferences.theme().colorTheme().applyToTheme( - mTheme, - LauncherPreferences.theme().textShadow() - ) - - return mTheme + return modifyTheme(super.getTheme()) } override fun onResume() { diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/UIObject.kt b/app/src/main/java/de/jrpie/android/launcher/ui/UIObject.kt index 51324f4..b292425 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/UIObject.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/UIObject.kt @@ -10,6 +10,7 @@ import android.view.WindowInsets import android.view.WindowInsetsController import android.view.WindowManager import de.jrpie.android.launcher.preferences.LauncherPreferences +import de.jrpie.android.launcher.preferences.theme.Background /** * An interface implemented by every [Activity], Fragment etc. in Launcher. @@ -65,8 +66,14 @@ interface UIObject { theme, LauncherPreferences.theme().textShadow() ) - LauncherPreferences.theme().background().applyToTheme(theme) - LauncherPreferences.theme().font().applyToTheme(theme) + + if (isHomeScreen()) { + Background.TRANSPARENT.applyToTheme(theme) + LauncherPreferences.clock().font().applyToTheme(theme) + } else { + LauncherPreferences.theme().background().applyToTheme(theme) + LauncherPreferences.theme().font().applyToTheme(theme) + } return theme } diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/settings/meta/SettingsFragmentMeta.kt b/app/src/main/java/de/jrpie/android/launcher/ui/settings/meta/SettingsFragmentMeta.kt index dea0bcf..759d8cd 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/settings/meta/SettingsFragmentMeta.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/settings/meta/SettingsFragmentMeta.kt @@ -132,7 +132,12 @@ class SettingsFragmentMeta : Fragment(), UIObject { startActivity(Intent(this.context, LegalInfoActivity::class.java)) } + // version binding.settingsMetaTextVersion.text = BuildConfig.VERSION_NAME + binding.settingsMetaTextVersion.setOnClickListener { + val deviceInfo = getDeviceInfo() + copyToClipboard(requireContext(), deviceInfo) + } } } diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/ClockView.kt b/app/src/main/java/de/jrpie/android/launcher/ui/widgets/ClockView.kt index 33c4888..54d3869 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/ClockView.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/widgets/ClockView.kt @@ -6,13 +6,13 @@ import android.view.LayoutInflater import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.isVisible import de.jrpie.android.launcher.actions.Gesture -import de.jrpie.android.launcher.databinding.ClockBinding +import de.jrpie.android.launcher.databinding.WidgetClockBinding import de.jrpie.android.launcher.preferences.LauncherPreferences import java.util.Locale class ClockView(context: Context, attrs: AttributeSet? = null, val appWidgetId: Int): ConstraintLayout(context, attrs) { - val binding: ClockBinding = ClockBinding.inflate(LayoutInflater.from(context), this, true) + val binding: WidgetClockBinding = WidgetClockBinding.inflate(LayoutInflater.from(context), this, true) init { initClock() setOnClicks() diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/DebugInfoView.kt b/app/src/main/java/de/jrpie/android/launcher/ui/widgets/DebugInfoView.kt new file mode 100644 index 0000000..d0ab70a --- /dev/null +++ b/app/src/main/java/de/jrpie/android/launcher/ui/widgets/DebugInfoView.kt @@ -0,0 +1,17 @@ +package de.jrpie.android.launcher.ui.widgets + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import androidx.constraintlayout.widget.ConstraintLayout +import de.jrpie.android.launcher.databinding.WidgetDebugInfoBinding +import de.jrpie.android.launcher.getDeviceInfo + +class DebugInfoView(context: Context, attrs: AttributeSet? = null, val appWidgetId: Int): ConstraintLayout(context, attrs) { + + val binding: WidgetDebugInfoBinding = WidgetDebugInfoBinding.inflate(LayoutInflater.from(context), this, true) + + init { + binding.debugInfoText.text = getDeviceInfo() + } +} \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/WidgetPanelActivity.kt b/app/src/main/java/de/jrpie/android/launcher/ui/widgets/WidgetPanelActivity.kt index 5217bff..4392451 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/WidgetPanelActivity.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/widgets/WidgetPanelActivity.kt @@ -3,6 +3,7 @@ package de.jrpie.android.launcher.ui.widgets import android.app.Activity import android.content.res.Resources import android.os.Bundle +import androidx.core.view.ViewCompat import de.jrpie.android.launcher.R import de.jrpie.android.launcher.databinding.ActivityWidgetPanelBinding import de.jrpie.android.launcher.preferences.LauncherPreferences @@ -12,13 +13,20 @@ import de.jrpie.android.launcher.widgets.WidgetPanel class WidgetPanelActivity : Activity(), UIObject { lateinit var binding: ActivityWidgetPanelBinding - var widgetPanelId: Int = WidgetPanel.Companion.HOME.id + private var widgetPanelId: Int = WidgetPanel.HOME.id override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) super.onCreate() - widgetPanelId = intent.getIntExtra(EXTRA_PANEL_ID, WidgetPanel.Companion.HOME.id) + widgetPanelId = intent.getIntExtra(EXTRA_PANEL_ID, WidgetPanel.HOME.id) val binding = ActivityWidgetPanelBinding.inflate(layoutInflater) setContentView(binding.root) + + // The widget container should extend below the status and navigation bars, + // so let's set an empty WindowInsetsListener to prevent it from being moved. + ViewCompat.setOnApplyWindowInsetsListener(binding.root) { _, windowInsets -> + windowInsets + } + binding.widgetPanelWidgetContainer.widgetPanelId = widgetPanelId binding.widgetPanelWidgetContainer.updateWidgets( this, @@ -38,6 +46,13 @@ class WidgetPanelActivity : Activity(), UIObject { return mTheme } + override fun onWindowFocusChanged(hasFocus: Boolean) { + super.onWindowFocusChanged(hasFocus) + + if (hasFocus && LauncherPreferences.display().hideNavigationBar()) { + hideNavigationBar() + } + } override fun onStart() { super.onStart() diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/ManageWidgetPanelsActivity.kt b/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/ManageWidgetPanelsActivity.kt index cb57fda..163777f 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/ManageWidgetPanelsActivity.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/ManageWidgetPanelsActivity.kt @@ -18,13 +18,16 @@ import de.jrpie.android.launcher.widgets.updateWidgetPanel class ManageWidgetPanelsActivity : AppCompatActivity(), UIObject { + @SuppressLint("NotifyDataSetChanged") private val sharedPreferencesListener = SharedPreferences.OnSharedPreferenceChangeListener { _, prefKey -> - if (prefKey == LauncherPreferences.widgets().keys().customPanels()) { + if ( + prefKey == LauncherPreferences.widgets().keys().customPanels() + || prefKey == LauncherPreferences.widgets().keys().widgets() + ) { viewAdapter.widgetPanels = (LauncherPreferences.widgets().customPanels() ?: setOf()).toTypedArray() - @SuppressLint("NotifyDataSetChanged") viewAdapter.notifyDataSetChanged() } } @@ -76,7 +79,6 @@ class ManageWidgetPanelsActivity : AppCompatActivity(), UIObject { ) ) } - true } } diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/ManageWidgetsActivity.kt b/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/ManageWidgetsActivity.kt index a841919..4b5c0c2 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/ManageWidgetsActivity.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/ManageWidgetsActivity.kt @@ -8,18 +8,21 @@ import android.content.res.Resources import android.graphics.Rect import android.os.Bundle import android.util.Log +import android.view.ViewGroup import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat -import com.google.android.material.floatingactionbutton.FloatingActionButton +import androidx.core.view.updateLayoutParams import de.jrpie.android.launcher.Application -import de.jrpie.android.launcher.R +import de.jrpie.android.launcher.databinding.ActivityManageWidgetsBinding import de.jrpie.android.launcher.preferences.LauncherPreferences import de.jrpie.android.launcher.ui.UIObject -import de.jrpie.android.launcher.ui.widgets.WidgetContainerView import de.jrpie.android.launcher.widgets.AppWidget +import de.jrpie.android.launcher.widgets.GRID_SIZE import de.jrpie.android.launcher.widgets.WidgetPanel import de.jrpie.android.launcher.widgets.WidgetPosition +import kotlin.math.max import kotlin.math.min +import kotlin.math.roundToInt // http://coderender.blogspot.com/2012/01/hosting-android-widgets-my.html @@ -30,14 +33,16 @@ const val REQUEST_PICK_APPWIDGET = 2 const val EXTRA_PANEL_ID = "widgetPanelId" // We can't use AppCompatActivity, since some AppWidgets don't work there. -class ManageWidgetsActivity : Activity(), UIObject { +class ManageWidgetsActivity : UIObject, Activity() { private var panelId: Int = WidgetPanel.HOME.id + private lateinit var binding: ActivityManageWidgetsBinding private var sharedPreferencesListener = SharedPreferences.OnSharedPreferenceChangeListener { _, prefKey -> if (prefKey == LauncherPreferences.widgets().keys().widgets()) { - findViewById(R.id.manage_widgets_container).updateWidgets(this, + binding.manageWidgetsContainer.updateWidgets( + this, LauncherPreferences.widgets().widgets() ) } @@ -46,21 +51,33 @@ class ManageWidgetsActivity : Activity(), UIObject { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) super.onCreate() - setContentView(R.layout.activity_manage_widgets) + binding = ActivityManageWidgetsBinding.inflate(layoutInflater) + setContentView(binding.root) panelId = intent.extras?.getInt(EXTRA_PANEL_ID, WidgetPanel.HOME.id) ?: WidgetPanel.HOME.id - findViewById(R.id.manage_widgets_button_add).setOnClickListener { + binding.manageWidgetsButtonAdd.setOnClickListener { selectWidget() } - ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> - val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) - v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) - insets + // The widget container should extend below the status and navigation bars, + // so let's set an empty WindowInsetsListener to prevent it from being moved. + ViewCompat.setOnApplyWindowInsetsListener(binding.root) { _, windowInsets -> + windowInsets } - findViewById(R.id.manage_widgets_container).let { + // The button must not be placed under the navigation bar + ViewCompat.setOnApplyWindowInsetsListener(binding.manageWidgetsButtonAdd) { v, windowInsets -> + val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) + v.updateLayoutParams { + leftMargin = insets.left + bottomMargin = insets.bottom + rightMargin = insets.right + } + WindowInsetsCompat.CONSUMED + } + + binding.manageWidgetsContainer.let { it.widgetPanelId = panelId it.updateWidgets(this, LauncherPreferences.widgets().widgets()) } @@ -77,20 +94,23 @@ class ManageWidgetsActivity : Activity(), UIObject { override fun onResume() { super.onResume() - findViewById(R.id.manage_widgets_container).updateWidgets(this, + binding.manageWidgetsContainer.updateWidgets( + this, LauncherPreferences.widgets().widgets() ) } + + override fun onWindowFocusChanged(hasFocus: Boolean) { + super.onWindowFocusChanged(hasFocus) + + if (hasFocus && LauncherPreferences.display().hideNavigationBar()) { + hideNavigationBar() + } + } + override fun getTheme(): Resources.Theme { - val mTheme = modifyTheme(super.getTheme()) - mTheme.applyStyle(R.style.backgroundWallpaper, true) - LauncherPreferences.clock().font().applyToTheme(mTheme) - LauncherPreferences.theme().colorTheme().applyToTheme( - mTheme, - LauncherPreferences.theme().textShadow() - ) - return mTheme + return modifyTheme(super.getTheme()) } override fun onDestroy() { @@ -100,7 +120,7 @@ class ManageWidgetsActivity : Activity(), UIObject { } - fun selectWidget() { + private fun selectWidget() { val appWidgetHost = (application as Application).appWidgetHost startActivityForResult( Intent(this, SelectWidgetActivity::class.java).also { @@ -117,7 +137,7 @@ class ManageWidgetsActivity : Activity(), UIObject { } - fun createWidget(data: Intent) { + private fun createWidget(data: Intent) { Log.i("Launcher", "creating widget") val appWidgetManager = (application as Application).appWidgetManager val appWidgetId = data.extras?.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID) ?: return @@ -126,13 +146,12 @@ class ManageWidgetsActivity : Activity(), UIObject { val display = windowManager.defaultDisplay - val position = WidgetPosition.fromAbsoluteRect( - Rect(0,0, - min(400, appWidgetManager.getAppWidgetInfo(appWidgetId).minWidth), - min(400, appWidgetManager.getAppWidgetInfo(appWidgetId).minHeight) - ), - display.width, - display.height + val widgetInfo = appWidgetManager.getAppWidgetInfo(appWidgetId) + + val position = WidgetPosition.findFreeSpace( + WidgetPanel.byId(panelId), + max(3, (GRID_SIZE * (widgetInfo.minWidth) / display.width.toFloat()).roundToInt()), + max(3, (GRID_SIZE * (widgetInfo.minHeight) / display.height.toFloat()).roundToInt()) ) val widget = AppWidget(appWidgetId, position, panelId, provider) diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/WidgetOverlayView.kt b/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/WidgetOverlayView.kt index 1b8a2d2..61006b8 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/WidgetOverlayView.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/WidgetOverlayView.kt @@ -2,11 +2,13 @@ package de.jrpie.android.launcher.ui.widgets.manage import android.content.Context import android.graphics.Canvas +import android.graphics.Color import android.graphics.Paint import android.graphics.Rect import android.graphics.drawable.Drawable import android.util.AttributeSet import android.view.View +import android.view.ViewGroup import android.widget.PopupMenu import androidx.core.graphics.toRectF import de.jrpie.android.launcher.R @@ -20,23 +22,32 @@ private const val HANDLE_EDGE_SIZE = (1.2 * HANDLE_SIZE).toInt() /** * An overlay to show configuration options for a widget in [WidgetManagerView] */ -class WidgetOverlayView : View { +class WidgetOverlayView : ViewGroup { + private val paint = Paint() + private val handlePaint = Paint() + private val selectedHandlePaint = Paint() + + private val popupAnchor = View(context) - val paint = Paint() - val handlePaint = Paint() - val selectedHandlePaint = Paint() var mode: WidgetManagerView.EditMode? = null + class Handle(val mode: WidgetManagerView.EditMode, val position: Rect) init { + addView(popupAnchor) + setWillNotDraw(false) handlePaint.style = Paint.Style.STROKE - handlePaint.setARGB(255, 255, 255, 255) + handlePaint.color = Color.WHITE + handlePaint.strokeWidth = 2f + handlePaint.setShadowLayer(10f,0f,0f, Color.BLACK) selectedHandlePaint.style = Paint.Style.FILL_AND_STROKE selectedHandlePaint.setARGB(100, 255, 255, 255) + handlePaint.setShadowLayer(10f,0f,0f, Color.BLACK) paint.style = Paint.Style.STROKE - paint.setARGB(255, 255, 255, 255) + paint.color = Color.WHITE + paint.setShadowLayer(10f,0f,0f, Color.BLACK) } private var preview: Drawable? = null @@ -75,21 +86,23 @@ class WidgetOverlayView : View { } } val bounds = getBounds() + canvas.drawRoundRect(bounds.toRectF(), 5f, 5f, paint) if (mode == null) { return } - //preview?.bounds = bounds //preview?.draw(canvas) + } - + override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) { + popupAnchor.layout(0,0,0,0) } fun showPopupMenu() { val widget = Widget.byId(context, widgetId)?: return - val menu = PopupMenu(context, this) + val menu = PopupMenu(context, popupAnchor) menu.menu.let { it.add( context.getString(R.string.widget_menu_remove) diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/WidgetPanelsRecyclerAdapter.kt b/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/WidgetPanelsRecyclerAdapter.kt index 40c2c2f..d27ba9a 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/WidgetPanelsRecyclerAdapter.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/WidgetPanelsRecyclerAdapter.kt @@ -26,10 +26,16 @@ class WidgetPanelsRecyclerAdapter( class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { var labelView: TextView = itemView.findViewById(R.id.list_widget_panels_label) + var infoView: TextView = itemView.findViewById(R.id.list_widget_panels_info) } override fun onBindViewHolder(viewHolder: ViewHolder, i: Int) { viewHolder.labelView.text = widgetPanels[i].label + val numWidgets = widgetPanels[i].getWidgets().size + viewHolder.infoView.text = context.resources.getQuantityString( + R.plurals.widget_panel_number_of_widgets, + numWidgets, numWidgets + ) viewHolder.itemView.setOnClickListener { onSelectWidgetPanel(widgetPanels[i]) diff --git a/app/src/main/java/de/jrpie/android/launcher/widgets/DebugInfoWidget.kt b/app/src/main/java/de/jrpie/android/launcher/widgets/DebugInfoWidget.kt new file mode 100644 index 0000000..01ecddc --- /dev/null +++ b/app/src/main/java/de/jrpie/android/launcher/widgets/DebugInfoWidget.kt @@ -0,0 +1,42 @@ +package de.jrpie.android.launcher.widgets + +import android.app.Activity +import android.content.Context +import android.graphics.drawable.Drawable +import android.view.View +import de.jrpie.android.launcher.ui.widgets.DebugInfoView +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + + +@Serializable +@SerialName("widget:debuginfo") +class DebugInfoWidget( + override val id: Int, + override var position: WidgetPosition, + override val panelId: Int, + override var allowInteraction: Boolean = true +) : Widget() { + + override fun createView(activity: Activity): View { + return DebugInfoView(activity, null, id) + } + + override fun findView(views: Sequence): DebugInfoView? { + return views.mapNotNull { it as? DebugInfoView }.firstOrNull { it.appWidgetId == id } + } + + override fun getPreview(context: Context): Drawable? { + return null + } + + override fun getIcon(context: Context): Drawable? { + return null + } + + override fun isConfigurable(context: Context): Boolean { + return false + } + + override fun configure(activity: Activity, requestCode: Int) { } +} \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/widgets/LauncherWidgetProvider.kt b/app/src/main/java/de/jrpie/android/launcher/widgets/LauncherWidgetProvider.kt index 018b29b..92f33a9 100644 --- a/app/src/main/java/de/jrpie/android/launcher/widgets/LauncherWidgetProvider.kt +++ b/app/src/main/java/de/jrpie/android/launcher/widgets/LauncherWidgetProvider.kt @@ -37,13 +37,14 @@ class LauncherAppWidgetProvider(val info: AppWidgetProviderInfo) : LauncherWidge } } -class LauncherClockWidgetProvider : LauncherWidgetProvider() { - override fun loadLabel(context: Context): CharSequence? { +data object LauncherClockWidgetProvider : LauncherWidgetProvider() { + + override fun loadLabel(context: Context): CharSequence { return context.getString(R.string.widget_clock_label) } - override fun loadDescription(context: Context): CharSequence? { + override fun loadDescription(context: Context): CharSequence { return context.getString(R.string.widget_clock_description) } @@ -54,5 +55,4 @@ class LauncherClockWidgetProvider : LauncherWidgetProvider() { override fun loadIcon(context: Context): Drawable? { return AppCompatResources.getDrawable(context, R.drawable.baseline_clock_24) } -} - +} \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/widgets/Widget.kt b/app/src/main/java/de/jrpie/android/launcher/widgets/Widget.kt index e31250b..28539a2 100644 --- a/app/src/main/java/de/jrpie/android/launcher/widgets/Widget.kt +++ b/app/src/main/java/de/jrpie/android/launcher/widgets/Widget.kt @@ -4,7 +4,6 @@ import android.app.Activity import android.content.Context import android.graphics.drawable.Drawable import android.view.View -import de.jrpie.android.launcher.Application import de.jrpie.android.launcher.preferences.LauncherPreferences import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json diff --git a/app/src/main/java/de/jrpie/android/launcher/widgets/WidgetPanel.kt b/app/src/main/java/de/jrpie/android/launcher/widgets/WidgetPanel.kt index 93e588d..e56983a 100644 --- a/app/src/main/java/de/jrpie/android/launcher/widgets/WidgetPanel.kt +++ b/app/src/main/java/de/jrpie/android/launcher/widgets/WidgetPanel.kt @@ -32,6 +32,12 @@ class WidgetPanel(val id: Int, var label: String) { .filter { it.panelId == this.id }.forEach { it.delete(context) } } + fun getWidgets(): List { + return LauncherPreferences.widgets().widgets().filter { + it.panelId == this.id + } + } + companion object { val HOME = WidgetPanel(0, "home") diff --git a/app/src/main/java/de/jrpie/android/launcher/widgets/WidgetPosition.kt b/app/src/main/java/de/jrpie/android/launcher/widgets/WidgetPosition.kt index b575665..e51f00c 100644 --- a/app/src/main/java/de/jrpie/android/launcher/widgets/WidgetPosition.kt +++ b/app/src/main/java/de/jrpie/android/launcher/widgets/WidgetPosition.kt @@ -11,9 +11,20 @@ const val GRID_SIZE: Short = 12 @Serializable data class WidgetPosition(var x: Short, var y: Short, var width: Short, var height: Short) { + constructor(rect: Rect) : this( + rect.left.toShort(), + rect.top.toShort(), + (rect.right - rect.left).toShort(), + (rect.bottom - rect.top).toShort() + ) + + fun toRect(): Rect { + return Rect(x.toInt(), y.toInt(), x + width, y + height) + } + fun getAbsoluteRect(screenWidth: Int, screenHeight: Int): Rect { val gridWidth = screenWidth / GRID_SIZE.toFloat() - val gridHeight= screenHeight / GRID_SIZE.toFloat() + val gridHeight = screenHeight / GRID_SIZE.toFloat() return Rect( (x * gridWidth).toInt(), @@ -23,25 +34,33 @@ data class WidgetPosition(var x: Short, var y: Short, var width: Short, var heig ) } + companion object { fun fromAbsoluteRect(absolute: Rect, screenWidth: Int, screenHeight: Int): WidgetPosition { val gridWidth = screenWidth / GRID_SIZE.toFloat() - val gridHeight= screenHeight / GRID_SIZE.toFloat() + val gridHeight = screenHeight / GRID_SIZE.toFloat() - val x = (absolute.left / gridWidth).roundToInt().toShort().coerceIn(0, (GRID_SIZE-1).toShort()) - val y = (absolute.top / gridHeight).roundToInt().toShort().coerceIn(0, (GRID_SIZE-1).toShort()) + val x = (absolute.left / gridWidth).roundToInt().toShort() + .coerceIn(0, (GRID_SIZE - 1).toShort()) + val y = (absolute.top / gridHeight).roundToInt().toShort() + .coerceIn(0, (GRID_SIZE - 1).toShort()) val w = max(2, ((absolute.right - absolute.left) / gridWidth).roundToInt()).toShort() val h = max(2, ((absolute.bottom - absolute.top) / gridHeight).roundToInt()).toShort() - return WidgetPosition(x,y,w,h) + return WidgetPosition(x, y, w, h) } - fun center(minWidth: Int, minHeight: Int, screenWidth: Int, screenHeight: Int): WidgetPosition { + fun center( + minWidth: Int, + minHeight: Int, + screenWidth: Int, + screenHeight: Int + ): WidgetPosition { val gridWidth = screenWidth / GRID_SIZE.toFloat() - val gridHeight= screenHeight / GRID_SIZE.toFloat() + val gridHeight = screenHeight / GRID_SIZE.toFloat() val cellsWidth = ceil(minWidth / gridWidth).toInt().toShort() val cellsHeight = ceil(minHeight / gridHeight).toInt().toShort() @@ -52,7 +71,32 @@ data class WidgetPosition(var x: Short, var y: Short, var width: Short, var heig cellsWidth, cellsHeight ) + } + fun findFreeSpace( + widgetPanel: WidgetPanel?, + minWidth: Int, + minHeight: Int + ): WidgetPosition { + val rect = Rect(0, 0, minWidth, minHeight) + if (widgetPanel == null) { + return WidgetPosition(rect) + } + + val widgets = widgetPanel.getWidgets().map { it.position.toRect() } + + for (x in 0.. { - val list = mutableListOf(LauncherClockWidgetProvider()) + val list = mutableListOf(LauncherClockWidgetProvider) val appWidgetManager = context.getAppWidgetManager() val profiles = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { @@ -68,11 +68,9 @@ fun getAppWidgetProviders( context: Context ): List { }.flatten() ) - return list } - fun updateWidget(widget: Widget) { LauncherPreferences.widgets().widgets( (LauncherPreferences.widgets().widgets() ?: setOf()) diff --git a/app/src/main/res/layout/home.xml b/app/src/main/res/layout/activity_home.xml similarity index 100% rename from app/src/main/res/layout/home.xml rename to app/src/main/res/layout/activity_home.xml diff --git a/app/src/main/res/layout/activity_manage_widgets.xml b/app/src/main/res/layout/activity_manage_widgets.xml index c77f0e3..66404ee 100644 --- a/app/src/main/res/layout/activity_manage_widgets.xml +++ b/app/src/main/res/layout/activity_manage_widgets.xml @@ -1,5 +1,6 @@ - + - \ No newline at end of file + + diff --git a/app/src/main/res/layout/list_widget_panels_row.xml b/app/src/main/res/layout/list_widget_panels_row.xml index 53f7449..835050f 100644 --- a/app/src/main/res/layout/list_widget_panels_row.xml +++ b/app/src/main/res/layout/list_widget_panels_row.xml @@ -1,6 +1,7 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/clock.xml b/app/src/main/res/layout/widget_clock.xml similarity index 100% rename from app/src/main/res/layout/clock.xml rename to app/src/main/res/layout/widget_clock.xml diff --git a/app/src/main/res/layout/widget_debug_info.xml b/app/src/main/res/layout/widget_debug_info.xml new file mode 100644 index 0000000..1de9e43 --- /dev/null +++ b/app/src/main/res/layout/widget_debug_info.xml @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 46fce3d..d399d12 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -406,8 +406,8 @@ Widget Panel #%1$d - Contains %d widget. - Contains %d widgets. + Contains %1$d widget. + Contains %1$d widgets. diff --git a/fastlane/metadata/android/en-US/changelogs/46.txt b/fastlane/metadata/android/en-US/changelogs/46.txt new file mode 100644 index 0000000..7d7f599 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/46.txt @@ -0,0 +1,2 @@ +* Fixed several bugs related to widgets +* Copy device info when clicking the version number (thank you, wassupluke!)