Search

PythonReactSEOPDF
GitHub Skill

search-guides

Search app step-by-step guides - adding new providers (5 steps), adding settings (4 steps), adding settings screens (5 steps), Room database migrations, common file locations table, naming conventions, package organization, and design patterns used.

mrndstvndv☆ 2 Repository stars1 Repository forks

Installation

Follow the repository instructions for this skill and your agent. Review the files and dependencies before adding it to your workflow.

View source ↗Guides

Skill instructions

Quick Reference Guides

Adding a New Provider

Step 1: Create Provider Class
app/src/main/java/com/mrndstvndv/search/provider/{type}/{Name}Provider.kt
Step 2: Implement Provider Interface
class NewProvider(
    private val context: Context,
    private val settingsRepository: ProviderSettingsRepository
) : Provider {
    
    override val id = "new-provider"
    override val displayName = "New Provider"
    override val refreshSignal = MutableSharedFlow<Unit>()
    
    override fun initialize() { /* Heavy setup */ }
    
    override fun canHandle(query: Query): Boolean {
        return query.text.isNotBlank()
    }
    
    override suspend fun query(query: Query): List<ProviderResult> {
        // Return search results
    }
    
    override fun dispose() { /* Cleanup */ }
}
Step 3: Register in MainActivity (~line 150)
val providers = remember {
    listOf(
        // ... existing providers
        NewProvider(context, settingsRepository)
    )
}
Step 4: Add Toggle in ProvidersSettingsScreen
SettingsSwitch(
    title = "New Provider",
    checked = isEnabled,
    onCheckedChange = { /* save state */ }
)
Step 5: Add to DEFAULT_PROVIDER_ORDER

In ProviderRankingRepository:

private val DEFAULT_PROVIDER_ORDER = listOf(
    // ... existing IDs
    "new-provider"
)

Adding a New Setting

Step 1: Add Key Constant

In ProviderSettingsRepository:

private const val KEY_NEW_SETTING = "new_setting"
Step 2: Add StateFlow
private val _newSetting = MutableStateFlow(loadNewSetting())
val newSetting: StateFlow<Boolean> = _newSetting.asStateFlow()
Step 3: Add Load/Save Methods
private fun loadNewSetting(): Boolean {
    return prefs.getBoolean(KEY_NEW_SETTING, true)
}

fun setNewSetting(value: Boolean) {
    prefs.edit().putBoolean(KEY_NEW_SETTING, value).apply()
    _newSetting.value = value
}
Step 4: Add UI

In the appropriate settings screen:

val newSetting by settingsRepository.newSetting.collectAsState()

SettingsSwitch(
    title = "New Setting",
    description = "Description of what this does",
    checked = newSetting,
    onCheckedChange = { settingsRepository.setNewSetting(it) }
)

Adding a New Settings Screen

Step 1: Create Screen File
app/src/main/java/com/mrndstvndv/search/ui/settings/NewSettingsScreen.kt
Step 2: Implement Composable
@Composable
fun NewSettingsScreen(
    settingsRepository: ProviderSettingsRepository,
    onNavigateBack: () -> Unit
) {
    Column {
        // Back button header
        TopAppBar(
            title = { Text("New Settings") },
            navigationIcon = {
                IconButton(onClick = onNavigateBack) {
                    Icon(Icons.AutoMirrored.Filled.ArrowBack, "Back")
                }
            }
        )
        
        // Settings content
        SettingsGroup(title = "Section") {
            // Settings components...
        }
    }
}
Step 3: Add to Screen Enum

In SettingsActivity.kt:

private enum class Screen {
    // ... existing screens
    NewScreen
}
Step 4: Add Navigation Case
Screen.NewScreen -> NewSettingsScreen(
    settingsRepository = settingsRepository,
    onNavigateBack = { currentScreen = Screen.Home }
)
Step 5: Add Navigation Row

In parent screen:

SettingsNavigationRow(
    title = "New Settings",
    onClick = { onNavigate(Screen.NewScreen) }
)

Database Migrations (Room)

Step 1: Update Entity

In provider/files/index/:

@Entity(tableName = "files")
data class FileEntity(
    @PrimaryKey val path: String,
    val name: String,
    val newColumn: String = ""  // Add new field
)
Step 2: Add Migration

In FileSearchDatabase:

val MIGRATION_1_2 = object : Migration(1, 2) {
    override fun migrate(database: SupportSQLiteDatabase) {
        database.execSQL(
            "ALTER TABLE files ADD COLUMN newColumn TEXT NOT NULL DEFAULT ''"
        )
    }
}
Step 3: Increment Version and Add Migration
@Database(entities = [FileEntity::class], version = 2)
abstract class FileSearchDatabase : RoomDatabase() {
    companion object {
        fun getInstance(context: Context) = Room.databaseBuilder(...)
            .addMigrations(MIGRATION_1_2)
            .build()
    }
}

Common File Locations

Task Location
Add new provider provider/{type}/{Name}Provider.kt
Add provider settings settings/ProviderSettingsRepository.kt
Add settings UI ui/settings/{Name}SettingsScreen.kt
Add reusable component ui/components/{ComponentName}.kt
Modify theme ui/theme/Theme.kt, Color.kt, Type.kt
Add permission AndroidManifest.xml
Add dependency gradle/libs.versions.toml + app/build.gradle.kts
Modify file search index provider/files/index/

Naming Conventions

Type Convention Example
Providers *Provider.kt AppListProvider.kt
Repositories *Repository.kt AliasRepository.kt
Settings Data *Settings WebSearchSettings
Composables PascalCase functions SearchField()
Screen files *Screen.kt GeneralSettingsScreen.kt
State variables camelCase with prefix isLoading, hasError

Package Organization

provider/
├── Provider.kt           # Base interface
├── ProviderResult.kt     # Result model
├── model/                # Shared models (Query, etc.)
├── {type}/               # Provider implementation
│   ├── {Type}Provider.kt
│   └── {Type}Repository.kt (if needed)

ui/
├── theme/                # Design system
├── components/           # Reusable components
│   └── settings/         # Settings-specific components
└── settings/             # Settings screens

settings/                 # Non-UI settings utilities
├── ProviderSettingsRepository.kt
└── ProviderRankingRepository.kt

Design Patterns Used

Pattern Usage Location
Provider Pattern Unified search source abstraction provider/Provider.kt
Repository Pattern Data access abstraction *Repository.kt files
Singleton Pattern Heavy shared resources FileSearchRepository
Observer Pattern Reactive settings via StateFlow All repositories
Sealed Classes Type-safe result/target hierarchies AliasTarget, ProviderResult
Fuzzy Matching Raycast-style character matching FuzzyMatcher.kt

Related Skills

  • search-overview - Project structure and architecture
  • search-provider - Provider interface details
  • search-repository - Repository patterns
  • search-ui - UI components and navigation
  • search-build - Build configuration

Examples

Read the usage examples in the source repository.

View source ↗

Source history

Indexed on
2026-01-20
Index updated
2026-02-03
Branch
main

Index and sync dates describe this directory. View the source repository for code history.

GitHub ↗

chat Comments (0)

chat_bubble_outline

No comments yet. Be the first to share your thoughts!