diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..1546e11 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +ai-secretary-app \ No newline at end of file diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml new file mode 100644 index 0000000..fdf8d99 --- /dev/null +++ b/.idea/kotlinc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/kotlin/com/example/aisecretary/MainActivity.kt b/app/src/main/kotlin/com/example/aisecretary/MainActivity.kt index dc485f6..c16449a 100644 --- a/app/src/main/kotlin/com/example/aisecretary/MainActivity.kt +++ b/app/src/main/kotlin/com/example/aisecretary/MainActivity.kt @@ -10,6 +10,12 @@ import androidx.navigation.fragment.NavHostFragment import androidx.navigation.ui.AppBarConfiguration import androidx.navigation.ui.navigateUp import androidx.navigation.ui.setupActionBarWithNavController +import androidx.appcompat.app.AppCompatDelegate +import com.example.aisecretary.settings.SettingsManager +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch class MainActivity : AppCompatActivity() { @@ -19,6 +25,18 @@ class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) + + // Apply dark mode setting + val settingsManager = SettingsManager(applicationContext) + CoroutineScope(Dispatchers.Main).launch { + settingsManager.darkModeEnabled.collectLatest { enabled -> + if (enabled) { + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) + } else { + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) + } + } + } // Setup toolbar setSupportActionBar(findViewById(R.id.toolbar)) diff --git a/app/src/main/kotlin/com/example/aisecretary/settings/SettingsManager.kt b/app/src/main/kotlin/com/example/aisecretary/settings/SettingsManager.kt index 854408c..a9eaae8 100644 --- a/app/src/main/kotlin/com/example/aisecretary/settings/SettingsManager.kt +++ b/app/src/main/kotlin/com/example/aisecretary/settings/SettingsManager.kt @@ -36,6 +36,12 @@ class SettingsManager(context: Context) { ) val autoActivateMic: StateFlow = _autoActivateMic.asStateFlow() + // Dark mode setting + private val _darkModeEnabled = MutableStateFlow( + preferences.getBoolean(KEY_DARK_MODE_ENABLED, false) + ) + val darkModeEnabled: StateFlow = _darkModeEnabled.asStateFlow() + fun isMemoryEnabled(): Boolean { return preferences.getBoolean(KEY_MEMORY_ENABLED, true) } @@ -72,11 +78,21 @@ class SettingsManager(context: Context) { _autoActivateMic.value = enabled } + fun isDarkModeEnabled(): Boolean { + return preferences.getBoolean(KEY_DARK_MODE_ENABLED, false) + } + + fun setDarkModeEnabled(enabled: Boolean) { + preferences.edit().putBoolean(KEY_DARK_MODE_ENABLED, enabled).apply() + _darkModeEnabled.value = enabled + } + companion object { private const val PREFS_NAME = "secretary_settings" private const val KEY_MEMORY_ENABLED = "memory_enabled" private const val KEY_VOICE_OUTPUT_ENABLED = "voice_output_enabled" private const val KEY_WAKE_WORD_ENABLED = "wake_word_enabled" private const val KEY_AUTO_ACTIVATE_MIC = "auto_activate_mic" + private const val KEY_DARK_MODE_ENABLED = "dark_mode_enabled" } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/example/aisecretary/ui/settings/SettingsFragment.kt b/app/src/main/kotlin/com/example/aisecretary/ui/settings/SettingsFragment.kt index bf31659..df3cbb8 100644 --- a/app/src/main/kotlin/com/example/aisecretary/ui/settings/SettingsFragment.kt +++ b/app/src/main/kotlin/com/example/aisecretary/ui/settings/SettingsFragment.kt @@ -22,6 +22,7 @@ class SettingsFragment : Fragment() { private lateinit var switchMemoryStorage: SwitchMaterial private lateinit var switchWakeWord: SwitchMaterial private lateinit var switchAutoActivateMic: SwitchMaterial + private lateinit var switchDarkMode: SwitchMaterial private lateinit var buttonSaveSettings: Button override fun onCreateView( @@ -42,6 +43,7 @@ class SettingsFragment : Fragment() { switchMemoryStorage = view.findViewById(R.id.switch_memory_storage) switchWakeWord = view.findViewById(R.id.switch_wake_word) switchAutoActivateMic = view.findViewById(R.id.switch_auto_activate_mic) + switchDarkMode = view.findViewById(R.id.switch_dark_mode) buttonSaveSettings = view.findViewById(R.id.button_save_settings) setupListeners() @@ -66,6 +68,10 @@ class SettingsFragment : Fragment() { viewModel.setAutoActivateMicEnabled(isChecked) } + switchDarkMode.setOnCheckedChangeListener { _, isChecked -> + viewModel.setDarkModeEnabled(isChecked) + } + buttonSaveSettings.setOnClickListener { viewModel.saveSettings() } @@ -104,6 +110,14 @@ class SettingsFragment : Fragment() { } } + viewLifecycleOwner.lifecycleScope.launch { + viewModel.darkModeEnabled.collectLatest { enabled -> + if (switchDarkMode.isChecked != enabled) { + switchDarkMode.isChecked = enabled + } + } + } + viewLifecycleOwner.lifecycleScope.launch { viewModel.settingsUpdated.collectLatest { updated -> if (updated) { diff --git a/app/src/main/kotlin/com/example/aisecretary/ui/settings/SettingsViewModel.kt b/app/src/main/kotlin/com/example/aisecretary/ui/settings/SettingsViewModel.kt index bee83a1..76f848c 100644 --- a/app/src/main/kotlin/com/example/aisecretary/ui/settings/SettingsViewModel.kt +++ b/app/src/main/kotlin/com/example/aisecretary/ui/settings/SettingsViewModel.kt @@ -29,6 +29,9 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application private val _autoActivateMicEnabled = MutableStateFlow(settingsManager.isAutoActivateMicEnabled()) val autoActivateMicEnabled: StateFlow = _autoActivateMicEnabled.asStateFlow() + private val _darkModeEnabled = MutableStateFlow(settingsManager.isDarkModeEnabled()) + val darkModeEnabled: StateFlow = _darkModeEnabled.asStateFlow() + private val _settingsUpdated = MutableStateFlow(false) val settingsUpdated: StateFlow = _settingsUpdated.asStateFlow() @@ -66,6 +69,12 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application _autoActivateMicEnabled.value = it } } + + viewModelScope.launch { + settingsManager.darkModeEnabled.collectLatest { + _darkModeEnabled.value = it + } + } } fun setVoiceInputEnabled(enabled: Boolean) { @@ -87,6 +96,10 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application fun setAutoActivateMicEnabled(enabled: Boolean) { _autoActivateMicEnabled.value = enabled } + + fun setDarkModeEnabled(enabled: Boolean) { + _darkModeEnabled.value = enabled + } fun saveSettings() { settingsManager.setVoiceOutputEnabled(_voiceInputEnabled.value) @@ -94,6 +107,7 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application settingsManager.setMemoryEnabled(_memoryEnabled.value) settingsManager.setWakeWordEnabled(_wakeWordEnabled.value) settingsManager.setAutoActivateMicEnabled(_autoActivateMicEnabled.value) + settingsManager.setDarkModeEnabled(_darkModeEnabled.value) _settingsUpdated.value = true } diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml index 123f1f5..cc301c9 100644 --- a/app/src/main/res/layout/fragment_settings.xml +++ b/app/src/main/res/layout/fragment_settings.xml @@ -129,6 +129,42 @@ + + + + + + + + + + + diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml new file mode 100644 index 0000000..48cec2d --- /dev/null +++ b/app/src/main/res/values-night/colors.xml @@ -0,0 +1,43 @@ + + + + #4F46E5 + #3730A3 + #818CF8 + + #0EA5E9 + #0284C7 + #38BDF8 + + #1F2937 + #111827 + #1F2937 + #111827 + #121212 + + #F3F4F6 + #9CA3AF + #6B7280 + #FFFFFF + #FFFFFF + + #10B981 + #F59E0B + #EF4444 + #EF4444 + #3B82F6 + + #4F46E5 + #23272F + #FFFFFF + #F3F4F6 + + #818CF8 + #4F46E5 + #3730A3 + #38BDF8 + #0284C7 + #FF000000 + #FFFFFFFF + #111827 + \ No newline at end of file diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml new file mode 100644 index 0000000..49f52fb --- /dev/null +++ b/app/src/main/res/values-night/themes.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 10f99df..9229fb0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -25,4 +25,6 @@ Auto-activate microphone after speaking Automatically start listening after Astra finishes speaking Cancel + Activate Dark Mode + Display Settings \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index bb418d3..0fbcf3a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -33,5 +33,5 @@ android.nonTransitiveRClass=true # Suppress unsupported compileSdk warning android.suppressUnsupportedCompileSdk=34 -# Use JDK 17 for the build -org.gradle.java.home=/usr/lib/jvm/java-17-openjdk \ No newline at end of file +# Use JDK 17 + upwards for the build +org.gradle.java.home=C\:\\Program Files\\Eclipse Adoptium\\jdk-17.0.16.8-hotspot \ No newline at end of file