Skip to content

Commit

Permalink
customised menu actions based on the app.config.json
Browse files Browse the repository at this point in the history
  • Loading branch information
aman-alfresco committed Sep 17, 2024
1 parent e0f2b1a commit 2df9e82
Show file tree
Hide file tree
Showing 9 changed files with 170 additions and 101 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,21 @@ package com.alfresco.content.actions
import com.airbnb.mvrx.Async
import com.airbnb.mvrx.MavericksState
import com.airbnb.mvrx.Uninitialized
import com.alfresco.content.data.AppMenu
import com.alfresco.content.data.ContextualActionData
import com.alfresco.content.data.Entry
import com.alfresco.content.data.MobileConfigDataEntry

data class ContextualActionsState(
val entries: List<Entry> = emptyList(),
val isMultiSelection: Boolean = false,
val actions: List<Action> = emptyList(),
val topActions: List<Action> = emptyList(),
val fetch: Async<Entry> = Uninitialized,
val mobileConfigDataEntry: MobileConfigDataEntry? = null,
val appMenu: List<AppMenu>? = null,
) : MavericksState {
constructor(target: ContextualActionData) : this(entries = target.entries, isMultiSelection = target.isMultiSelection,
mobileConfigDataEntry = target.mobileConfigData)
constructor(target: ContextualActionData) : this(
entries = target.entries,
isMultiSelection = target.isMultiSelection,
appMenu = target.appMenu,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,20 @@ import com.airbnb.mvrx.Success
import com.airbnb.mvrx.ViewModelContext
import com.alfresco.content.common.EntryListener
import com.alfresco.content.data.BrowseRepository
import com.alfresco.content.data.CommonRepository.Companion.KEY_FEATURES_MOBILE
import com.alfresco.content.data.Entry
import com.alfresco.content.data.FavoritesRepository
import com.alfresco.content.data.MenuActions
import com.alfresco.content.data.SearchRepository
import com.alfresco.content.data.SearchRepository.Companion.SERVER_VERSION_NUMBER
import com.alfresco.content.data.Settings
import com.alfresco.content.data.getJsonFromSharedPrefs
import com.alfresco.coroutines.asFlow
import com.alfresco.events.on
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.launch

class ContextualActionsViewModel(
state: ContextualActionsState,
val state: ContextualActionsState,
val context: Context,
private val settings: Settings,
) : MavericksViewModel<ContextualActionsState>(state) {
Expand Down Expand Up @@ -138,13 +137,17 @@ class ContextualActionsViewModel(
when {
state.entries.all { it.isTrashed } -> {
// Added restore and delete actions
actions.add(ActionRestore(entry, state.entries))
actions.add(ActionDeleteForever(entry, state.entries))
actions.addAll(
listOfNotNull(
if (isMenuActionEnabled(MenuActions.Restore)) ActionRestore(entry, state.entries) else null,
if (isMenuActionEnabled(MenuActions.PermanentlyDelete)) ActionDeleteForever(entry, state.entries) else null,
),
)
}

state.entries.all { it.hasOfflineStatus } -> {
// Added Offline action
actions.add(offlineMultiActionFor(entry, state.entries))
actions.addAll(offlineMultiActionFor(entry, state.entries))
}

else -> {
Expand All @@ -161,30 +164,39 @@ class ContextualActionsViewModel(
// Added Favorite Action
val version = SearchRepository().getPrefsServerVersion()

if (version.toInt() >= SERVER_VERSION_NUMBER) {
if (entries.any { !it.isFavorite }) {
actions.add(ActionAddFavorite(entry, entries))
} else {
actions.add(ActionRemoveFavorite(entry, entries))
}
val hasNonFavoriteEntries = entries.any { !it.isFavorite }

val favouriteActions = when {
version.toInt() < SERVER_VERSION_NUMBER -> null
hasNonFavoriteEntries && isMenuActionEnabled(MenuActions.AddFavourite) -> ActionAddFavorite(entry, entries)
!hasNonFavoriteEntries && isMenuActionEnabled(MenuActions.RemoveFavourite) -> ActionRemoveFavorite(entry, entries)
else -> null
}

actions.addAll(listOfNotNull(favouriteActions))

// Added Start Process Action
processMultiActionFor(entry, entries)?.let { action ->
actions.add(action)
}
actions.addAll(processMultiActionFor(entry, entries))

// Added Move Action
if (isMoveDeleteAllowed(entries)) {
actions.add(ActionMoveFilesFolders(entry, entries))
actions.addAll(
listOfNotNull(
if (isMenuActionEnabled(MenuActions.Move)) ActionMoveFilesFolders(entry, entries) else null,
),
)
}

// Added Offline Action
actions.add(offlineMultiActionFor(entry, entries))
actions.addAll(offlineMultiActionFor(entry, entries))

// Added Delete Action
if (isMoveDeleteAllowed(entries)) {
actions.add((ActionDelete(entry, entries)))
actions.addAll(
listOfNotNull(
if (isMenuActionEnabled(MenuActions.Trash)) ActionDelete(entry, entries) else null,
),
)
}
return actions
}
Expand All @@ -200,7 +212,10 @@ class ContextualActionsViewModel(
).flatten()

private fun actionsForTrashed(entry: Entry): List<Action> =
listOf(ActionRestore(entry), ActionDeleteForever(entry))
listOfNotNull(
if (isMenuActionEnabled(MenuActions.Restore)) ActionRestore(entry) else null,
if (isMenuActionEnabled(MenuActions.PermanentlyDelete)) ActionDeleteForever(entry) else null,
)

private fun actionsForOffline(entry: Entry): List<Action> =
listOf(
Expand All @@ -210,68 +225,106 @@ class ContextualActionsViewModel(
).flatten()

private fun actionsProcesses(entry: Entry): List<Action> =
listOf(ActionStartProcess(entry))

private fun processMultiActionFor(entry: Entry, entries: List<Entry>): Action? {
if (settings.isProcessEnabled && (entries.isNotEmpty() && entries.all { it.isFile })) {
return ActionStartProcess(entry, entries)
listOfNotNull(
if (isMenuActionEnabled(MenuActions.StartProcess)) ActionStartProcess(entry) else null,
)

private fun processMultiActionFor(entry: Entry, entries: List<Entry>): List<Action> {
return if (settings.isProcessEnabled && (entries.isNotEmpty() && entries.all { it.isFile })) {
listOfNotNull(
if (isMenuActionEnabled(MenuActions.StartProcess)) ActionStartProcess(entry, entries) else null,
)
} else {
emptyList()
}
return null
}

private fun offlineActionFor(entry: Entry) =
if (!entry.isFile && !entry.isFolder) {
listOf()
} else if (entry.hasOfflineStatus && !entry.isOffline) {
listOf()
} else {
listOf(if (entry.isOffline) ActionRemoveOffline(entry) else ActionAddOffline(entry))
private fun offlineActionFor(entry: Entry): List<Action> {
if (!entry.isFile && !entry.isFolder || (entry.hasOfflineStatus && !entry.isOffline)) {
return emptyList()
}

private fun offlineMultiActionFor(entry: Entry, entries: List<Entry>): Action {
return listOfNotNull(
when {
entry.isOffline && isMenuActionEnabled(MenuActions.RemoveOffline) -> ActionRemoveOffline(entry)
!entry.isOffline && isMenuActionEnabled(MenuActions.AddOffline) -> ActionAddOffline(entry)
else -> null
},
)
}

private fun offlineMultiActionFor(entry: Entry, entries: List<Entry>): List<Action> {
val filteredOffline = entries.filter { it.isFile || it.isFolder }.filter { !it.hasOfflineStatus || it.isOffline }

return if (filteredOffline.any { !it.isOffline }) {
ActionAddOffline(entry, entries)
} else {
ActionRemoveOffline(entry, entries)
return when {
filteredOffline.any { !it.isOffline } -> {
listOfNotNull(
if (isMenuActionEnabled(MenuActions.AddOffline)) ActionAddOffline(entry, entries) else null,
)
}

else -> {
listOfNotNull(
if (isMenuActionEnabled(MenuActions.RemoveOffline)) ActionRemoveOffline(entry, entries) else null,
)
}
}
}

private fun favoriteActionFor(entry: Entry) =
listOf(if (entry.isFavorite) ActionRemoveFavorite(entry) else ActionAddFavorite(entry))
private fun favoriteActionFor(entry: Entry): List<Action> =
listOfNotNull(
when {
entry.isFavorite && isMenuActionEnabled(MenuActions.RemoveFavourite) -> ActionRemoveFavorite(entry)
!entry.isFavorite && isMenuActionEnabled(MenuActions.AddFavourite) -> ActionAddFavorite(entry)
else -> null
},
)

private fun externalActionsFor(entry: Entry) =
private fun externalActionsFor(entry: Entry): List<Action> =
if (entry.isFile) {
listOf(ActionOpenWith(entry), ActionDownload(entry))
listOfNotNull(
if (isMenuActionEnabled(MenuActions.OpenWith)) ActionOpenWith(entry) else null,
if (isMenuActionEnabled(MenuActions.Download)) ActionDownload(entry) else null,
)
} else {
listOf()
emptyList()
}

private fun deleteActionFor(entry: Entry) = if (entry.canDelete) listOf(ActionDelete(entry)) else listOf()
private fun deleteActionFor(entry: Entry) = if (entry.canDelete) listOfNotNull(if (isMenuActionEnabled(MenuActions.Trash)) ActionDelete(entry) else null) else listOf()

private fun renameMoveActionFor(entry: Entry): List<Action> {
val actions = mutableListOf<Action>()
if (entry.canDelete && (entry.isFile || entry.isFolder)) {
actions.add(ActionUpdateFileFolder(entry))
actions.add(ActionMoveFilesFolders(entry))
return if (entry.canDelete && (entry.isFile || entry.isFolder)) {
listOfNotNull(
if (isMenuActionEnabled(MenuActions.Rename)) ActionUpdateFileFolder(entry) else null,
if (isMenuActionEnabled(MenuActions.Move)) ActionMoveFilesFolders(entry) else null,
)
} else {
emptyList()
}
return actions
}

private fun makeTopActions(entry: Entry): List<Action> {
val actions = mutableListOf<Action>()
if (!entry.hasOfflineStatus) {
if (entry.isFavorite) {
actions.add(ActionRemoveFavorite(entry))
} else {
actions.add(ActionAddFavorite(entry))
}
}
if (entry.isFile) {
actions.add(ActionDownload(entry))
private fun makeTopActions(entry: Entry): List<Action> =
listOfNotNull(
// Add or Remove favorite actions based on favorite status
when {
!entry.hasOfflineStatus -> when {
entry.isFavorite && isMenuActionEnabled(MenuActions.RemoveFavourite) -> ActionRemoveFavorite(entry)
!entry.isFavorite && isMenuActionEnabled(MenuActions.AddFavourite) -> ActionAddFavorite(entry)
else -> null
}

else -> null
},
// Download action if entry is a file
if (entry.isFile && isMenuActionEnabled(MenuActions.Download)) ActionDownload(entry) else null,
)

private fun isMenuActionEnabled(menuActions: MenuActions): Boolean {
if (state.appMenu?.isEmpty() == true) {
return true
}
return actions

return state.appMenu?.find { it.id.lowercase() == menuActions.value.lowercase() }?.enabled == true
}

companion object : MavericksViewModelFactory<ContextualActionsViewModel, ContextualActionsState> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,16 @@ class LoginActivity : com.alfresco.auth.activity.LoginActivity() {
val session = Session(context, account)
val person = PeopleRepository(session).me()
val myFiles = BrowseRepository(session).myFilesNodeId()
AnalyticsManager(session).apiTracker(APIEvent.Login, true)
CommonRepository(session).getMobileConfigData()
processAccountInformation(person, myFiles, credentials, authConfig, endpoint)
AnalyticsManager(session).apiTracker(APIEvent.Login, true)
if (isExtension) {
navigateToExtension()
} else {
navigateToMain()
}
} catch (ex: Exception) {
ex.printStackTrace()
onError(R.string.auth_error_wrong_credentials)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,6 @@ private val formatter = DateTimeFormatterBuilder()
.optionalStart().appendOffset("+HHMM", "Z").optionalEnd()
.toFormatter()



// Function to store a JSON object
fun saveJsonToSharedPrefs(context: Context, key: String, obj: Any) {
val sharedPreferences: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
Expand All @@ -170,7 +168,6 @@ fun saveJsonToSharedPrefs(context: Context, key: String, obj: Any) {
editor.apply()
}


// Function to retrieve a JSON object
inline fun <reified T> getJsonFromSharedPrefs(context: Context, key: String): T? {
val sharedPreferences: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
Expand All @@ -186,5 +183,3 @@ inline fun <reified T> getJsonFromSharedPrefs(context: Context, key: String): T?
null
}
}


28 changes: 2 additions & 26 deletions data/src/main/kotlin/com/alfresco/content/data/CommonRepository.kt
Original file line number Diff line number Diff line change
@@ -1,44 +1,20 @@
package com.alfresco.content.data

import com.alfresco.content.apis.MobileConfigApi
import com.alfresco.content.session.ActionSessionInvalid
import com.alfresco.content.session.Session
import com.alfresco.content.session.SessionManager
import com.alfresco.content.session.SessionNotFoundException
import com.alfresco.events.EventBus
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import retrofit2.http.Url
import java.net.URL

class CommonRepository(otherSession: Session? = null) {

lateinit var session: Session
private val coroutineScope = CoroutineScope(Dispatchers.Main)

init {
try {
session = otherSession ?: SessionManager.requireSession
} catch (e: SessionNotFoundException) {
e.printStackTrace()
coroutineScope.launch {
EventBus.default.send(ActionSessionInvalid(true))
}
}
}

private val context get() = session.context
class CommonRepository(val session: Session = SessionManager.requireSession) {

private val service: MobileConfigApi by lazy {
session.createService(MobileConfigApi::class.java)
}

suspend fun getMobileConfigData() {

val data = MobileConfigDataEntry.with(service.getMobileConfig("https://${URL(session.account.serverUrl).host}/app-config.json"))

saveJsonToSharedPrefs(context, KEY_FEATURES_MOBILE, data)
saveJsonToSharedPrefs(session.context, KEY_FEATURES_MOBILE, data)
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ import kotlinx.parcelize.Parcelize
data class ContextualActionData(
val entries: List<Entry> = emptyList(),
val isMultiSelection: Boolean = false,
val mobileConfigData: MobileConfigDataEntry? = null,
val appMenu: List<AppMenu> = emptyList(),
) : Parcelable {
companion object {

fun withEntries(entries: List<Entry>, isMultiSelection: Boolean = false, mobileConfigData: MobileConfigDataEntry? = null): ContextualActionData {
return ContextualActionData(
entries = entries,
isMultiSelection = isMultiSelection,
mobileConfigData = mobileConfigData
appMenu = mobileConfigData?.featuresMobile?.menus ?: emptyList(),
)
}
}
Expand Down
Loading

0 comments on commit 2df9e82

Please sign in to comment.