Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,17 @@
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service
android:name=".app.QuickCreateTileService"
android:exported="true"
android:icon="@drawable/ic_quick_create_tile"
android:label="New Object"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter>
<meta-data android:name="android.service.quicksettings.ACTIVE_TILE" android:value="true" />
</service>
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package com.anytypeio.anytype.app

import android.content.Context
import android.content.ComponentName
import android.content.Intent
import android.service.quicksettings.TileService
import androidx.core.content.pm.ShortcutInfoCompat
import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.graphics.drawable.IconCompat
import com.anytypeio.anytype.R
import com.anytypeio.anytype.domain.misc.AppActionManager
import com.anytypeio.anytype.ui.main.MainActivity
import com.anytypeio.anytype.app.QuickCreateTileService
import timber.log.Timber

/**
Expand Down Expand Up @@ -44,6 +47,7 @@ class DefaultAppActionManager(val context: Context) : AppActionManager {
val shortcuts = ShortcutManagerCompat.getDynamicShortcuts(context).map { it.id }
ShortcutManagerCompat.removeLongLivedShortcuts(context, shortcuts)
ShortcutManagerCompat.removeAllDynamicShortcuts(context)
setupQuickCreateTile(null, null)
}

private fun setupCreateNewObjectAction(
Expand All @@ -66,10 +70,26 @@ class DefaultAppActionManager(val context: Context) : AppActionManager {
)
.build()
ShortcutManagerCompat.pushDynamicShortcut(context, shortcut)

if (action.isDefault) {
setupQuickCreateTile(action.type.key, label)
}
}

private fun setupQuickCreateTile(typeKey: String?, label: String?) {
val prefs = context.getSharedPreferences(QUICK_CREATE_TILE_PREFS, Context.MODE_PRIVATE)
val editor = prefs.edit()
editor.putString("typeKey", typeKey)
editor.putString("label", label)
editor.apply()

val componentName = ComponentName(context.applicationContext, QuickCreateTileService::class.java)
TileService.requestListeningState(context, componentName)
}

companion object {
const val ACTION_CREATE_NEW_ID = "anytype.app-action.create-new.id"
const val ACTION_CREATE_NEW_TYPE_KEY = "anytype.app-action.create-new.key"
const val QUICK_CREATE_TILE_PREFS = "anytype.quick-create-tile"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.anytypeio.anytype.app

import android.annotation.SuppressLint
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import android.service.quicksettings.Tile
import android.service.quicksettings.TileService
import com.anytypeio.anytype.ui.main.MainActivity

/**
* Quick Settings tile service that allows creating new objects from the quick settings panel.
*
* The tile's behavior is configured through shared preferences:
* - typeKey: The type of object to create when clicked
* - label: The display label for the tile
*
* The tile will be unavailable if no type is configured, and greyed out (but clickable) when it's set.
* When clicked, it launches MainActivity with an intent to create a new object of the configured type.
*/
class QuickCreateTileService : TileService() {
private var typeKey: String? = null

@SuppressLint("StartActivityAndCollapseDeprecated")
override fun onClick() {
super.onClick()
unlockAndRun {
val intent = Intent(Intent.ACTION_VIEW, null).apply {
setClass(applicationContext, MainActivity::class.java)
putExtra(DefaultAppActionManager.ACTION_CREATE_NEW_TYPE_KEY, typeKey)
flags = Intent.FLAG_ACTIVITY_NEW_TASK
}

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
val pendingIntent = PendingIntent.getActivity(
applicationContext,
0, // request code
intent,
PendingIntent.FLAG_IMMUTABLE
)
startActivityAndCollapse(pendingIntent)
} else {
startActivityAndCollapse(intent)
}
}
}

override fun onStartListening() {
super.onStartListening()
updateTile()
}

private fun updateTile() {
val prefs = getSharedPreferences(DefaultAppActionManager.QUICK_CREATE_TILE_PREFS, Context.MODE_PRIVATE)
typeKey = prefs.getString("typeKey", null)

val tile = qsTile
tile.state = if (typeKey != null) Tile.STATE_INACTIVE else Tile.STATE_UNAVAILABLE
tile.label = prefs.getString("label", "New Object")
tile.updateTile()
}
}
20 changes: 20 additions & 0 deletions app/src/main/res/drawable/ic_quick_create_tile.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="57dp"
android:height="57dp"
android:viewportWidth="57"
android:viewportHeight="57">
<group>
<clip-path
android:pathData="M-24.54,-25.802L86.56,-25.802L86.56,85.298L-24.54,85.298Z"/>
<path
android:pathData="M17.375,12.578L17.375,20.152L38.586,20.082L38.586,12.578L17.375,12.578zM38.586,20.152L38.586,39.371A11.536,11.536 0,0 1,46.664 35.895L46.664,20.152L38.586,20.152zM24.445,25.203C18.305,25.203 13.336,30.172 13.336,36.313C13.336,42.453 18.305,47.422 24.445,47.422C30.586,47.422 35.555,42.453 35.555,36.313C35.555,30.172 30.586,25.203 24.445,25.203z"
android:fillColor="#ffffff"/>
</group>
<path
android:pathData="m46.79,56.521q-3.777,0 -6.44,-2.662 -2.662,-2.662 -2.662,-6.44 0,-3.777 2.662,-6.44 2.662,-2.662 6.44,-2.662 3.777,0 6.44,2.662 2.662,2.662 2.662,6.44 0,3.777 -2.662,6.44 -2.662,2.662 -6.44,2.662zM45.879,52.88h1.82v-4.551h4.551v-1.82h-4.551v-4.551h-1.82v4.551h-4.551v1.82h4.551z"
android:strokeLineJoin="miter"
android:strokeWidth="4"
android:fillColor="#ffffff"
android:strokeColor="#00000000"
android:strokeLineCap="square"/>
</vector>
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ interface AppActionManager {
fun setup(actions: List<Action.CreateNew>)

sealed class Action {
data class CreateNew(val type: TypeKey, val name: String) : Action()
data class CreateNew(val type: TypeKey, val name: String, val isDefault: Boolean = false) : Action()
object ClearAll: Action()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1715,7 +1715,8 @@ class HomeScreenViewModel(
if (type.map.containsKey(Relations.UNIQUE_KEY)) {
AppActionManager.Action.CreateNew(
type = TypeKey(type.uniqueKey),
name = type.name.orEmpty()
name = type.name.orEmpty(),
isDefault = defaultObjectType?.key == type.uniqueKey
)
} else {
null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,16 @@ class PersonalizationSettingsViewModel(
)
).process(
success = { wrappers ->
val defaultObjectType = getDefaultObjectType.async(SpaceId(spaceManager.get())).getOrNull()?.type
val types = wrappers
.map { ObjectWrapper.Type(it.map) }
.sortedBy { keys.indexOf(it.uniqueKey) }

val actions = types.map { type ->
AppActionManager.Action.CreateNew(
type = TypeKey(type.uniqueKey),
name = type.name.orEmpty()
name = type.name.orEmpty(),
isDefault = type.uniqueKey == defaultObjectType?.key
)
}
appActionManager.setup(actions = actions)
Expand Down