Reorganize and group modules

This commit is contained in:
MM20
2022-12-13 17:37:26 +01:00
parent bac24baad2
commit 3f8880a90a
995 changed files with 501 additions and 298 deletions

View File

@@ -0,0 +1,79 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* 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 com.android.launcher3
import android.annotation.TargetApi
import android.content.ComponentName
import android.content.Intent
import android.graphics.RectF
import android.os.*
import android.util.Log
import android.view.SurfaceControl
import de.mm20.launcher2.ktx.isAtLeastApiLevel
/**
* Class to encapsulate the handshake protocol between Launcher and gestureNav.
*/
class GestureNavContract(
val componentName: ComponentName,
val user: UserHandle,
private val mCallback: Message
) {
/**
* Sends the position information to the receiver
*/
@TargetApi(Build.VERSION_CODES.R)
fun sendEndPosition(position: RectF? = null, surfaceControl: SurfaceControl? = null) {
val result = Bundle()
result.putParcelable(EXTRA_ICON_POSITION, position)
result.putParcelable(EXTRA_ICON_SURFACE, surfaceControl)
val callback = Message.obtain()
callback.copyFrom(mCallback)
callback.data = result
try {
callback.replyTo.send(callback)
} catch (e: RemoteException) {
Log.e(TAG, "Error sending icon position", e)
}
}
companion object {
private const val TAG = "GestureNavContract"
const val EXTRA_GESTURE_CONTRACT = "gesture_nav_contract_v1"
const val EXTRA_ICON_POSITION = "gesture_nav_contract_icon_position"
const val EXTRA_ICON_SURFACE = "gesture_nav_contract_surface_control"
const val EXTRA_REMOTE_CALLBACK = "android.intent.extra.REMOTE_CALLBACK"
/**
* Clears and returns the GestureNavContract if it was present in the intent.
*/
fun fromIntent(intent: Intent): GestureNavContract? {
if (!isAtLeastApiLevel(Build.VERSION_CODES.R)) {
return null
}
val extras = intent.getBundleExtra(EXTRA_GESTURE_CONTRACT)
?: return null
intent.removeExtra(EXTRA_GESTURE_CONTRACT)
val componentName = extras.getParcelable<ComponentName>(Intent.EXTRA_COMPONENT_NAME)
val userHandle = extras.getParcelable<UserHandle>(Intent.EXTRA_USER)
val callback = extras.getParcelable<Message>(EXTRA_REMOTE_CALLBACK)
return if (componentName != null && userHandle != null && callback != null && callback.replyTo != null
) {
GestureNavContract(componentName, userHandle, callback)
} else null
}
}
}

View File

@@ -0,0 +1,48 @@
package de.mm20.launcher2.debug
import android.content.Context
import android.os.Build
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.File
import java.text.SimpleDateFormat
import java.util.*
class DebugInformationDumper {
suspend fun dump(context: Context): String {
val df = SimpleDateFormat("yyyy-MM-dd-HHmmss")
val file = File(
context.getExternalFilesDir(null),
"kvaesitso-log-${df.format(Date(System.currentTimeMillis()))}"
)
withContext(Dispatchers.IO) {
val fos = file.outputStream().writer()
fos.write("Device: ${Build.DEVICE}\n")
fos.write("SDK version: ${Build.VERSION.SDK_INT}\n")
fos.write("====================================\n")
val input =
Runtime.getRuntime().exec("/system/bin/logcat -d").inputStream.bufferedReader()
var line = input.readLine()
while (line != null) {
line = input.readLine()
fos.write("$line\n")
}
fos.close()
}
return file.absolutePath
}
suspend fun exportDatabases(context: Context): String {
val df = SimpleDateFormat("yyyy-MM-dd-HHmmss")
val exportFile = File(
context.getExternalFilesDir(null),
"room-${df.format(Date(System.currentTimeMillis()))}.db"
)
withContext(Dispatchers.IO) {
context.getDatabasePath("room").copyTo(exportFile)
}
return exportFile.absolutePath
}
}

View File

@@ -0,0 +1,58 @@
package de.mm20.launcher2.graphics
import android.content.Context
import android.graphics.*
import android.graphics.drawable.AdaptiveIconDrawable
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.graphics.drawable.LayerDrawable
import androidx.core.graphics.drawable.toBitmap
import de.mm20.launcher2.ktx.dp
import kotlin.math.roundToInt
class BadgeDrawable(context: Context, drawable: Drawable) : Drawable() {
private val drawable: BitmapDrawable
init {
val size = (28.8 * context.dp).roundToInt()
val drw: Drawable = if (drawable is AdaptiveIconDrawable) {
LayerDrawable(arrayOf(
drawable.background,
drawable.foreground
)).apply {
val inset = (-size * 0.25).roundToInt()
setLayerInset(1, inset, inset, inset, inset)
setLayerInset(0, inset, inset, inset, inset)
}
} else {
drawable
}
val bitmap = drw.toBitmap(size, size).run {
if(isMutable) this
else this.copy(config, true)
}
this.drawable = BitmapDrawable(context.resources, bitmap)
}
override fun setAlpha(alpha: Int) {
}
@Deprecated("Deprecated in super class")
override fun getOpacity(): Int {
return PixelFormat.TRANSLUCENT
}
override fun setColorFilter(colorFilter: ColorFilter?) {
}
override fun draw(canvas: Canvas) {
canvas.clipPath(Path().apply { addOval(
bounds.left.toFloat(),
bounds.top.toFloat(),
bounds.right.toFloat(),
bounds.bottom.toFloat(), Path.Direction.CW) })
drawable.setBounds(bounds.left, bounds.top, bounds.right, bounds.bottom)
drawable.draw(canvas)
}
}

View File

@@ -0,0 +1,17 @@
package de.mm20.launcher2.helper
import android.content.Context
import android.net.ConnectivityManager
object NetworkUtils {
fun isOffline(context: Context, allowMobile: Boolean = true): Boolean {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val info = connectivityManager.activeNetworkInfo ?: return true
return when {
info.type == ConnectivityManager.TYPE_WIFI -> false
info.type == ConnectivityManager.TYPE_MOBILE && allowMobile -> false
else -> true
}
}
}

View File

@@ -0,0 +1,12 @@
package de.mm20.launcher2.icons
sealed interface LauncherIcon
data class StaticLauncherIcon(
val foregroundLayer: LauncherIconLayer,
val backgroundLayer: LauncherIconLayer,
): LauncherIcon
interface DynamicLauncherIcon: LauncherIcon {
suspend fun getIcon(time: Long): StaticLauncherIcon
}

View File

@@ -0,0 +1,50 @@
package de.mm20.launcher2.icons
import android.graphics.drawable.Drawable
sealed interface LauncherIconLayer
data class StaticIconLayer(
val icon: Drawable,
val scale: Float = 1f,
) : LauncherIconLayer
data class ColorLayer(
val color: Int = 0,
) : LauncherIconLayer
data class ClockLayer(
val sublayers: List<ClockSublayer>,
val scale: Float,
) : LauncherIconLayer
data class ClockSublayer(
val drawable: Drawable,
val role: ClockSublayerRole
)
enum class ClockSublayerRole {
Hour,
Minute,
Second,
Static,
}
data class TintedIconLayer(
val icon: Drawable,
val scale: Float = 0.5f,
val color: Int = 0
) : LauncherIconLayer
data class TintedClockLayer(
val sublayers: List<ClockSublayer>,
val scale: Float,
val color: Int = 0,
) : LauncherIconLayer
data class TextLayer(
val text: String,
val color: Int = 0,
) : LauncherIconLayer
object TransparentLayer: LauncherIconLayer

View File

@@ -0,0 +1,17 @@
package de.mm20.launcher2.licenses
import android.content.Context
import de.mm20.launcher2.base.R
object AppLicense {
fun get(context: Context): OpenSourceLibrary {
return OpenSourceLibrary(
name = context.getString(R.string.app_name),
description = context.getString(R.string.preference_about_license),
copyrightNote = "Copyright (C) 20212022 MM2-0 and the Kvæsitso contributors",
licenseName = R.string.gpl3_name,
licenseText = R.raw.license_gpl_3,
url = "https://github.com/MM2-0/Kvaesitso"
)
}
}

View File

@@ -0,0 +1,13 @@
package de.mm20.launcher2.licenses
import androidx.annotation.RawRes
import androidx.annotation.StringRes
data class OpenSourceLibrary(
val name: String,
val description: String? = null,
@StringRes val licenseName: Int,
val copyrightNote: String? = null,
@RawRes val licenseText: Int,
val url: String
)

View File

@@ -0,0 +1,226 @@
package de.mm20.launcher2.licenses
import de.mm20.launcher2.base.R
val OpenSourceLicenses = arrayOf(
OpenSourceLibrary(
name = "Kotlin Standard Library",
description = " A modern programming language that makes developers happier.",
licenseName = R.string.apache_license_name,
licenseText = R.raw.license_apache_2,
url = "https://kotlinlang.org/"
),
OpenSourceLibrary(
name = "KotlinX Coroutines",
description = "Library support for Kotlin coroutines",
licenseName = R.string.apache_license_name,
licenseText = R.raw.license_apache_2,
url = "https://github.com/Kotlin/kotlinx.coroutines"
),
OpenSourceLibrary(
name = "KotlinX Collections",
description = "Immutable collection interfaces and implementation prototypes for Kotlin.",
licenseName = R.string.apache_license_name,
licenseText = R.raw.license_apache_2,
url = "https://github.com/Kotlin/kotlinx.collections.immutable"
),
OpenSourceLibrary(
name = "Android Jetpack",
description = "A collection of Android software components to make it easier to develop great Android apps.",
licenseName = R.string.apache_license_name,
licenseText = R.raw.license_apache_2,
url = "https://developer.android.com/jetpack"
),
OpenSourceLibrary(
name = "Accompanist",
description = "Accompanist is a group of libraries that aim to supplement Jetpack Compose with features that are commonly required by developers but not yet available.",
licenseName = R.string.apache_license_name,
licenseText = R.raw.license_apache_2,
copyrightNote = "Copyright 2020 The Android Open Source Project",
url = "https://google.github.io/accompanist/"
),
OpenSourceLibrary(
name = "Material Components for Android",
description = "Material Components for Android (MDC-Android) help developers execute Material Design.",
licenseName = R.string.apache_license_name,
licenseText = R.raw.license_apache_2,
url = "https://material.io/develop/android/"
),
OpenSourceLibrary(
name = "OkHttp",
description = "An HTTP & HTTP/2 client for Android and Java applications",
licenseName = R.string.apache_license_name,
licenseText = R.raw.license_apache_2,
copyrightNote = "Copyright 2019 Square, Inc.",
url = "https://square.github.io/okhttp/"
),
OpenSourceLibrary(
name = "Retrofit",
description = "A type-safe HTTP client for Android and Java",
licenseName = R.string.apache_license_name,
licenseText = R.raw.license_apache_2,
copyrightNote = "Copyright 2013 Square, Inc.",
url = "https://square.github.io/retrofit/"
),
OpenSourceLibrary(
name = "Gson",
description = "Gson is a Java library that can be used to convert Java Objects into their JSON representation.",
licenseName = R.string.apache_license_name,
licenseText = R.raw.license_apache_2,
copyrightNote = "Copyright 2008 Google Inc.",
url = "https://github.com/google/gson/"
),
OpenSourceLibrary(
name = "commons-suncalc",
description = "A Java library for calculation of sun and moon positions and phases.",
licenseName = R.string.apache_license_name,
licenseText = R.raw.license_apache_2,
url = "https://github.com/shred/commons-suncalc"
),
OpenSourceLibrary(
name = "Jsoup",
description = "A Java library for working with real-world HTML",
licenseName = R.string.mit_license_name,
licenseText = R.raw.license_mit,
copyrightNote = "Copyright (c) 2009-2021 Jonathan Hedley <https://jsoup.org/>",
url = "https://jsoup.org/"
),
OpenSourceLibrary(
name = "mXparser (Version 4.4.2)",
description = "A super easy, rich, fast and highly flexible math expression parser library",
licenseName = R.string.bsd_2clause_name,
licenseText = R.raw.license_bsd_2clause,
copyrightNote = "Copyright 2010 - 2020 Mariusz Gromada. All rights reserved.",
url = "https://mathparser.org/"
),
OpenSourceLibrary(
name = "Google Auth Library",
description = "Open source authentication client library for Java.",
licenseName = R.string.bsd_3clause_name,
licenseText = R.raw.license_bsd_3clause,
copyrightNote = "Copyright 2014, Google Inc. All rights reserved.",
url = "https://github.com/googleapis/google-auth-library-java"
),
OpenSourceLibrary(
name = "Google APIs Client Library for Android",
description = "The Google APIs Client Library for Java is a flexible, efficient, and powerful Java client library for accessing any HTTP-based API on the web, not just Google APIs.",
licenseName = R.string.apache_license_name,
licenseText = R.raw.license_apache_2,
url = "https://github.com/googleapis/google-api-java-client"
),
OpenSourceLibrary(
name = "Microsoft Graph SDK for Java",
description = "Get started with the Microsoft Graph SDK for Java by integrating the Microsoft Graph API into your Java application!",
licenseName = R.string.mit_license_name,
licenseText = R.raw.license_mit,
copyrightNote = "Copyright (c) 2018 Microsoft Graph",
url = "https://github.com/microsoftgraph/msgraph-sdk-java"
),
OpenSourceLibrary(
name = "Microsoft Authentication Library (MSAL) for Android",
description = "The MSAL library for Android gives your app the ability to use the Microsoft Cloud by supporting Microsoft Azure Active Directory and Microsoft accounts in a converged experience using industry standard OAuth2 and OpenID Connect. The library also supports Azure AD B2C.",
licenseName = R.string.mit_license_name,
licenseText = R.raw.license_mit,
copyrightNote = "Copyright (c) Microsoft Corporation",
url = "https://github.com/AzureAD/microsoft-authentication-library-for-android"
),
OpenSourceLibrary(
name = "CrashReporter",
description = "CrashReporter is a handy tool to capture app crashes and save them in a file.",
licenseName = R.string.apache_license_name,
licenseText = R.raw.license_apache_2,
copyrightNote = "Copyright (C) 2016 Bal Sikandar\nCopyright (C) 2011 Android Open Source Project",
url = "https://github.com/MindorksOpenSource/CrashReporter"
),
OpenSourceLibrary(
name = "Material Design Icons",
description = "Beautifully crafted, delightful, and easy to use in your web, Android, and iOS projects",
licenseName = R.string.apache_license_name,
licenseText = R.raw.license_apache_2,
url = "https://material.io/icons/"
),
OpenSourceLibrary(
name = "Koin",
description = "A smart Kotlin injection library to keep you focused on your app, not on your tools",
licenseName = R.string.apache_license_name,
licenseText = R.raw.license_apache_2,
url = "https://insert-koin.io/"
),
OpenSourceLibrary(
name = "Outfit",
description = "A geometric sans serif typeface",
copyrightNote = "Copyright 2021 The Outfit Project Authors",
licenseName = R.string.open_font_license_name,
licenseText = R.raw.license_ofl,
url = "https://github.com/Outfitio/Outfit-Fonts"
),
OpenSourceLibrary(
name = "Coil",
description = "An image loading library for Android backed by Kotlin Coroutines",
copyrightNote = "Copyright 2021 Coil Contributors",
licenseName = R.string.apache_license_name,
licenseText = R.raw.license_apache_2,
url = "https://coil-kt.github.io/coil/"
),
OpenSourceLibrary(
name = "compose-color-picker",
description = "A component that provides an HSV color picker, written in Jetpack compose.",
copyrightNote = "Copyright (c) 2021GoDaddy Operating Company, LLC.",
licenseName = R.string.mit_license_name,
licenseText = R.raw.license_mit,
url = "https://github.com/godaddy/compose-color-picker"
),
OpenSourceLibrary(
name = "Apache Commons Text",
description = "Apache Commons Text is a library focused on algorithms working on strings. ",
licenseName = R.string.apache_license_name,
licenseText = R.raw.license_apache_2,
url = "https://commons.apache.org/proper/commons-text/"
),
OpenSourceLibrary(
name = "TinyPinyin",
description = "A fast, low-memory Chinese character-to-pinyin library for Java and Android.",
licenseName = R.string.apache_license_name,
licenseText = R.raw.license_apache_2,
url = "https://github.com/promeG/TinyPinyin"
),
OpenSourceLibrary(
name = "material-color-utilities",
copyrightNote = "Copyright 2021 Google LLC",
description = "Algorithms and utilities that power the Material Design 3 (M3) color system, including choosing theme colors from images and creating tones of colors; all in a new color space.",
licenseName = R.string.apache_license_name,
licenseText = R.raw.license_apache_2,
url = "https://github.com/material-foundation/material-color-utilities"
),
OpenSourceLibrary(
name = "Launcher3",
copyrightNote = "Copyright (C) 2020 The Android Open Source Project",
description = "The AOSP launcher",
licenseName = R.string.apache_license_name,
licenseText = R.raw.license_apache_2,
url = "https://source.android.com/"
),
OpenSourceLibrary(
name = "Lottie",
copyrightNote = "Copyright (c) 2017 Airbnb",
description = "Lottie is a library for Android, iOS, Web, and Windows that parses Adobe After Effects animations exported as json with Bodymovin and renders them natively on mobile and on the web",
licenseName = R.string.mit_license_name,
licenseText = R.raw.license_mit,
url = "https://airbnb.design/lottie/"
),
OpenSourceLibrary(
name = "Protobuf",
copyrightNote = "Copyright 2008 Google Inc. All rights reserved.",
description = "Protocol buffers are a language-neutral, platform-neutral extensible mechanism for serializing structured data.",
licenseName = R.string.bsd_3clause_name,
licenseText = R.raw.license_bsd_3clause,
url = "https://developers.google.com/protocol-buffers"
),
OpenSourceLibrary(
name = "AndroidSVG",
description = "AndroidSVG is a SVG parser and renderer for Android.",
licenseName = R.string.apache_license_name,
licenseText = R.raw.license_apache_2,
url = "https://bigbadaboom.github.io/androidsvg/"
),
)

View File

@@ -0,0 +1,33 @@
package de.mm20.launcher2.lifecycle
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import androidx.lifecycle.LiveData
class BroadcastReceiverLiveData<T>(
context: Context,
private val intentFilter: IntentFilter,
private val transformFunction: (Context, Intent) -> T
): LiveData<T>() {
private val context = context.applicationContext
private val receiver = object: BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val newValue = transformFunction(context, intent)
postValue(newValue)
}
}
override fun onActive() {
super.onActive()
context.registerReceiver(receiver, intentFilter)
}
override fun onInactive() {
super.onInactive()
context.unregisterReceiver(receiver)
}
}

View File

@@ -0,0 +1,44 @@
package de.mm20.launcher2.search
import android.content.Context
import android.os.Bundle
import de.mm20.launcher2.icons.LauncherIcon
import de.mm20.launcher2.icons.StaticLauncherIcon
import de.mm20.launcher2.ktx.romanize
import java.text.Collator
interface SavableSearchable : Searchable, Comparable<SavableSearchable> {
val domain: String
val key: String
val label: String
val labelOverride: String?
get() = null
fun overrideLabel(label: String): SavableSearchable
fun launch(context: Context, options: Bundle?): Boolean
/**
* If this is true, tapping the item will open the details popup instead of launching it
*/
val preferDetailsOverLaunch: Boolean
fun getPlaceholderIcon(context: Context): StaticLauncherIcon
suspend fun loadIcon(
context: Context,
size: Int,
themed: Boolean
): LauncherIcon? = null
override fun compareTo(other: SavableSearchable): Int {
val label1 = labelOverride ?: label
val label2 = other.labelOverride ?: other.label
return Collator.getInstance().apply { strength = Collator.SECONDARY }
.compare(label1.romanize(), label2.romanize())
}
}

View File

@@ -0,0 +1,3 @@
package de.mm20.launcher2.search
interface Searchable

View File

@@ -0,0 +1,12 @@
package de.mm20.launcher2.search
interface SearchableDeserializer {
fun deserialize(serialized: String): SavableSearchable?
}
class NullDeserializer: SearchableDeserializer {
override fun deserialize(serialized: String): SavableSearchable? {
return null
}
}

View File

@@ -0,0 +1,16 @@
package de.mm20.launcher2.search
interface SearchableSerializer {
fun serialize(searchable: SavableSearchable): String?
val typePrefix: String
}
class NullSerializer : SearchableSerializer {
override fun serialize(searchable: SavableSearchable): String? {
return null
}
override val typePrefix: String
get() = "null"
}