AndroidIDEOfficial / AndroidIDE

AndroidIDE is an IDE for Android to develop full featured Android apps.
https://m.androidide.com
GNU General Public License v3.0
2.1k stars 251 forks source link

[Feature]: Resource Manager #1319

Open Ruan625Br opened 9 months ago

Ruan625Br commented 9 months ago

Feature description

Resource Manager's Objective:

The Resource Manager was added to simplify access to resources in the project. The initial approach included the following points:

  1. Display a list of all resources from all project modules.
  2. Allow the selection of multiple resources.
  3. Show XML images from the "mipmap" and "drawable" folders.

However, after a review, the approach was adjusted as follows:

  1. Display a list of resources only from the "app" module (for now).
  2. Instead of directly displaying XML images from the "mipmap" and "drawable" folders, an alternative solution was implemented.
Structure
Resource Manager Structure
EditorActivityKt ResourceListFragment - Drawable ResourceListFragment - Color ResourceListFragment - Layout
img1 img2 img3 img4

Video on the official AndroidIDE channel on Telegram

Simple way to add new resource

  resourceInfoList.add(ResourceInfo(
      name = "Layout",
      file = File(layoutPath),
      resourceType = ResourceType.LAYOUT))

These changes aim to simplify the use of the Resource Manager and enhance the user experience when accessing and selecting resources in the project.

What version of AndroidIDE you're using?

v2.5.2 (debug builds)

Duplicate issues

Code of Conduct

MrIkso commented 9 months ago

I think add new activity not good idea. Try refactoring code , using a fragment

Ruan625Br commented 9 months ago

I wanted to create the ResourceManagerFragment for the SidebarAction, but I think there would be little space.

Ruan625Br commented 9 months ago

Using fragment

MrIkso commented 9 months ago

Looking not bad

Rafael2616 commented 9 months ago

Looks pretty cool..

MatheusTGP commented 9 months ago

Impressive. In line with AndroidIDE's design principles, specifically adhering to Material Design guidelines, it's worth considering the addition of a Floating Action Button (FAB) within the parent layout of the ResourceManagerFragment, positioned independently of the individual resource fragments. This FAB could dynamically adapt its functionality based on the user's context. For instance, when the user navigates to the Color section, it could facilitate the creation of new color resources and seamlessly extend this capability to other relevant resource types.

Moreover, to address concerns related to screen real estate, an alternative approach could involve integrating a discrete action button, strategically positioned at the bottom right corner of the "Resource Manager" title within the view. This approach not only conserves screen space but also ensures accessibility and usability.

These recommendations are offered as creative solutions to enhance the user experience and align with modern design standards, aiming to elevate the overall functionality and aesthetics of the ResourceManagerFragment. I hope this suggestion proves helpful.

Ruan625Br commented 9 months ago

Impressionante. De acordo com os princípios de design do AndroidIDE, aderindo especificamente às diretrizes de Design de Material, vale a pena considerar a adição de um Botão de Ação Flutuante (FAB) dentro do layout pai do , posicionado independentemente dos fragmentos de recursos individuais. Essa FAB poderia adaptar dinamicamente sua funcionalidade com base no contexto do usuário. Por exemplo, quando o usuário navega para a seção Cor, isso pode facilitar a criação de novos recursos de cores e estender perfeitamente esse recurso a outros tipos de recursos relevantes.ResourceManagerFragment

Além disso, para resolver preocupações relacionadas a imóveis na tela, uma abordagem alternativa poderia envolver a integração de um botão de ação discreto, estrategicamente posicionado no canto inferior direito do título "Gerenciador de Recursos" dentro da exibição. Essa abordagem não apenas conserva o espaço da tela, mas também garante acessibilidade e usabilidade.

Essas recomendações são oferecidas como soluções criativas para melhorar a experiência do usuário e se alinhar aos padrões modernos de design, visando elevar a funcionalidade geral e a estética do . Espero que esta sugestão seja útil.ResourceManagerFragment

I'll look into it, thanks for the opinion.

itsaky commented 9 months ago

@Ruan625Br Please make the layout more compact. We don't really need square previews of the colors. You could make the color previews circular or a rectangle with the height same as the two textviews (i.e. the bottom of the color preview should be aligned to the bottom of the second textview).

Also, instead of showing the color integers, it should show the HEX string for the colors.

Ruan625Br commented 9 months ago

I'll do that, I forgot to convert integers to hex.

itsaky commented 9 months ago

I'll do that, I forgot to convert integers to hex.

Why convert integers to hex? The colors are defined as hex strings in colors.xml file, right?

Ruan625Br commented 9 months ago

Yes, but I don't read the colors.xml file directly, but rather all the .xml files inside the values folder

Ruan625Br commented 9 months ago

Sim, mas eu não leio o arquivo .xml cores diretamente, mas sim todos os arquivos .xml dentro da pasta de valores

and after I refactor the code I will use this same way to read strings, colors... in an xml file with just one code

itsaky commented 9 months ago

Yes, but I don't read the colors.xml file directly, but rather all the .xml files inside the values folder

Instead of reading the XML files manually, you could make use of the resource tables that are generated after the project is initialized. It could work something like this :

  1. Once the project is initialized, get list of Android modules from IProjectManager.
  2. Then, get the resource table for the selected Android module with AndroidModule.getResourceTable().
  3. Using the ResourceTable, get the ResourceTablePackage for the selected module's package name.

The ResourceTablePackage contains all the resources from the given package name (module). You can find examples of this in the XML LSP module's completion providers.

Also, you need to add a dropdown menu which should let the user select the Android module (only Android modules). The resource manager should show resources for the selected module only.

Ruan625Br commented 9 months ago

Interesting, this is the way I read colors:

fun findAllColorsInXmlFiles(file: File): List<ColorInfo> {
     val results = mutableListOf<ColorInfo>()
     val log = ILogger.newInstance("ColorUtils")

     if (!file.isDirectory)
       return results

     val xmlFilePattern = Pattern.compile(".*\\.xml$")

     file.listFiles { _, name -> xmlFilePattern.matcher(name).matches() }
       ?.forEach { xmlFile ->
         try {
           val xmlContent = xmlFile.readText(Charset.defaultCharset())
           val pattern = "<color name=\"([^\"]+)\">#([A-Fa-f0-9]+)</color>".toPattern()
           val matcher = pattern.matcher(xmlContent)

           while (matcher.find()) {
             val colorName = matcher.group(1)
             val colorHex = matcher.group(2)
             val colorValue = Color.parseColor("#$colorHex")
             results.add(ColorInfo(xmlFile, colorName!!, colorValue))
           }
         } catch (e: Exception) {
           log.error("Failed to get colors", e)

         }
       }

     return results
   }

Initially I had in mind to create a data class to store the search result within the xml file, this way we could look for values not defined directly in the code, we would have reusable code.


After obtaining the colors, I convert the ColorInfo to ResourceItem:

 if (type == ResourceType.COLOR) {
          val colorList = ColorUtils.findAllColorsInXmlFiles(path.toFile())
          colorList.map { resourceList.add(it.toResourceItem()) }
          Success(resourceList as List<ResourceItem>)

  }

Converter:

fun ColorInfo.toResourceItem(): ResourceItem {
  return ResourceItem(
    name = colorName,
    info = colorValue.toString(),
    type = ResourceType.COLOR,
    file = file
  )
}

I intend to add path observer in the future, this way we would know when a file was changed, it will stay inside the ResourceListLiveData. This Observer is used by file managers (I used it myself in my file manager)

All of this occurs in the ResourceListLiveData and the result is sent to the ResourceListMapLiveData then we have access to the result through the ResourceListViewModel.